2012-10-05 39 views
1

我有一個可能很長的對象的Python列表。在特定時間,我對列表中具有某個屬性的所有元素(例如flag)感興趣,該元素的評估結果爲False。爲此,我一直在使用列表理解,像這樣:有效使用Python列表解析

objList = list() 
# ... populate list 
[x for x in objList if not x.flag] 

這似乎很好。形成子表後,我有可能需要做一些不同的操作:

  1. 標中的子表索引ind得到的元素。
  2. 計算子列表的長度(即具有flag == False的元素的數量)。
  3. 搜索子列表用於特定對象的第一個實例(使用列表的.index()方法即)。

我已經實現了這些使用幼稚的方法,只是形成子列表,然後使用它的方法來獲取我想要的數據。我想知道是否有更有效的方法去解決這些問題。 #1和#3至少看起來像他們可以優化,因爲在#1我只需要第一個ind + 1匹配元素的子列表,不一定是整個結果集,在#3我只需要通過子列表搜索直到我找到了一個匹配元素。

有沒有一個很好的Pythonic方法來做到這一點?我猜我可能會以某種方式使用()語法來獲取生成器,而不是創建整個列表,但我還沒有以正確的方式發生。我顯然可以手動編寫循環,但我正在尋找像基於理解的方法一樣優雅的東西。

回答

2

如果你需要做這些操作了幾次,其他方法的開銷會更高的,該列表是最好的方式。它也可能是最清晰的,所以如果記憶不是問題,那麼我建議你只是去用它。

如果內存/速度是一個問題,那麼有替代品 - 注意,速度的角度來看,這些實際上可能會比較慢,這取決於你的軟件常見的情況。

對於您的情況:

#value = sublist[n] 
value = nth(x for x in objList if not x.flag, n) 

#value = len(sublist) 
value = sum(not x.flag for x in objList) 

#value = sublist.index(target) 
value = next(dropwhile(lambda x: x != target, (x for x in objList if not x.flag))) 

運用迭代工具文檔itertools.dropwhile()the nth() recipe

+0

爲什麼'使用()'而不是'nnth()'? – kennytm

+0

@KennyTM好的建議,應該有點閱讀 - 編輯使用''nth()'',這是一個更好的解決方案 - 沒有意義重新發明輪子。 –

1

我會假設你可以做任何的這三樣東西,你可能會做他們不止一次。

在這種情況下,你想要什麼基本上是寫一個懶洋洋地評估列表類。它會保留兩個數據,一個是真實list緩存的評估項目,其餘的發電機。那麼你可以做ll[10]並會評估到10個項目,ll.index('spam'),它會評估,直到找到'spam',然後len(ll),它將評估列表的其餘部分,在現實列表中的所有,而緩存它認爲這樣沒有什麼比做一次。

構建它應該是這樣的:

LazyList(x for x in obj_list if not x.flag) 

但沒有什麼實際上將被計算,直到你真正開始使用它上面的。

+0

用這種方法,我需要某種方式通知LazyList實例,如果底層列表發生變化。我在OP中對此沒有明確說明,但是'objList'可以在我搜索它的時間之間改變。 –

+0

在這種情況下,您只需創建一個新的'LazyList'。 – fletom

1

既然你評論說,你objList可以改變的,如果你不需要索引或搜索objList本身,那麼你可能會更好只是儲存兩種不同的列表,一個與.flag = True和一個與.flag = False。然後您可以直接使用第二個列表,而不是每次都使用列表理解來構造它。

如果這適用於您的情況,它可能是最有效的方法。