2013-03-22 15 views
0

性能,優美和可讀性要求我有字典的數組「的最佳途徑」將對象的兩個元素添加到列表而不重複它們的最佳方式是什麼?

items = [ 
    {'id1' : 1, 'id2' : 2, 'other' : 'xxx'}, 
    {'id1' : 1, 'id2' : 3, 'other' : 'yyy'}, 
    {'id1' : 2, 'id2' : 4, 'other' : 'zzz'} 
] 

結果應該是:ids = [1,2,3,4](ID1和ID2的列表)

編輯: 事情是這樣的:

ids = [] 
for item in items: 
    if item.id1 not in ids: 
     ids.append(item.id1) 
    if item.id2 not in ids: 
     ids.append(item.id2) 
+0

請注意,這些值實際上沒有排序。除非你明確要'id1'和'id2'。你需要原始訂單嗎? – jamylak 2013-03-22 13:13:51

回答

4
>>> set(x for y in items for x in y.values()) 
set([1, 2, 3, 4]) 

更新更新的問題

>>> set(v for y in items for (k,v) in y.items() if k.startswith('id')) 
set([1, 2, 3, 4]) 
+0

我忘了提及字典中還有其他元素,只是想要一個id列表。 – 2013-03-22 13:14:07

+0

@ShankarCabus什麼定義了一個id?還有哪些其他元素?您在這裏沒有給我們足夠的信息。 – 2013-03-22 13:14:42

3

這可以通過使用itertools.chain.from_iterable()扁平化嵌套generator expression生產的id的值很容易做到 - 我們假設所有的按鍵都將成爲字符串,並且以"id"開頭指定一個id。然後,我們做出的各種價值觀,以消除重複:

from itertools import chain 

set(chain.from_iterable((value for name, value in item.items() 
         if name.startswith("id")) 
         for item in items)) 

如果你真的想要一個列表,那麼你可以創建一個自定,但在大多數情況下,設定應該罰款原樣。請注意,該集合沒有訂單,因此如果您想要訂單,則需要使用sorted()

itertools.chain.from_iterable()是壓扁迭代最有效和可讀的方法。

當談到身份證是什麼時,您的規範不清楚。如果你有一組鍵定義一個id,那麼像這樣的東西可能會更適合作爲內部生成器表達式的if子句:

if name in {"id1", "id2"} 
+0

檢查構建的組件的成員資格,這會花費比元組更長的時間。儘管時間會稍長一些。 – jamylak 2013-03-22 13:23:31

+0

@jamylak確實如此,但它通常並不重要,我傾向於使用一個集合,因爲當一組可能性很大(唯一可能很重要的情況)時,這是一個好習慣。 – 2013-03-22 13:24:32

相關問題