2014-02-24 57 views
3

我有一些1或2維的數據。我想遍歷數據集中的每個模式並對其執行foo()。如果數據是1D,那麼將此值添加到列表中,如果它是2D,則取內部列表的平均值並追加此值。 我看到this question,並決定實施它檢查列表的實例。我不能在這個應用程序中使用numpy。檢查Python中的多維列表

outputs = [] 
    for row in data: 
     if isinstance(row, list): 
      vals = [foo(window) for window in row] 
      outputs.append(sum(vals)/float(len(vals))) 
     else: 
      outputs.append(foo(row)) 

有沒有更好的方法做到這一點?在每次運行中,每個模式將具有相同的維度,所以我可以爲1D/2D創建一個單獨的類,但這會爲我的代碼添加很多類。數據集可能會變得很大,所以快速解決方案更可取。

+0

我會檢查hasattr(行[0], '\ __ ITER \ __'),而不是isinstance(),但我不認爲有一個更快的方式或更優雅的方式。 – knitti

+1

看起來很整潔我 – ForgetfulFellow

+0

參見http://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable。 – alecxe

回答

2

您的代碼已經幾乎像它一樣整潔。只有輕微改善正在取代[foo(window) for window in row]map(foo, row),可以由基準可以看出:

> python -m timeit "foo = lambda x: x+1; list(map(foo, range(1000)))" 
10000 loops, best of 3: 132 usec per loop 
> python -m timeit "foo = lambda x: x+1; [foo(a) for a in range(1000)]" 
10000 loops, best of 3: 140 usec per loop 

isinstance()似乎已經比它的同行hasattr()type() ==更快:

> python -m timeit "[isinstance(i, int) for i in range(1000)]" 
10000 loops, best of 3: 117 usec per loop 
> python -m timeit "[hasattr(i, '__iter__') for i in range(1000)]" 
1000 loops, best of 3: 470 usec per loop 
> python -m timeit "[type(i) == int for i in range(1000)]" 
10000 loops, best of 3: 130 usec per loop 


但是,如果算上短小整齊,還可以簡化你的代碼(代替map到:

mean = lambda x: sum(x)/float(len(x)) #or `from statistics import mean` in python3.4 
output = [foo(r) if isinstance(r, int) else mean(map(foo, r)) for r in data]