2017-04-07 75 views
0
[('a',), ('b',), ('a',)] 

產生將元組列表整理爲列表元組字典,其中元組的長度未知?

​​
[('a', 1.0), ('b', 2.0), ('a', 3.0)] 

產生

{'a': ([1.0, 3.0],), 'b': ([2.0],)} 

[('a', 1.0, 0.1), ('b', 2.0, 0.2), ('a', 1.0, 0.3)] 

產生

{'a': ([1.0, 1.0], [0.1, 0.3]), 'b': ([2.0], [0.2])} 

[('a', 1.0, 0.1, 7), ('b', 2.0, 0.2, 8), ('a', 1.0, 0.3, 9)] 

產生

{'a': ([1.0, 1.0], [0.1, 0.3], [7, 9]), 'b': ([2.0], [0.2], [8])} 

我是新來的Python - 這是我想出了。

def Collate(list_of_tuples): 
    if len(list_of_tuples)==0 or len(list_of_tuples[0])==0: 
     return defaultdict(tuple) 
    d = defaultdict(lambda: tuple([] for i in range(len(list_of_tuples[0])-1))) 
    for t in list_of_tuples: 
     d[t[0]] 
     for i,v in enumerate(t): 
      if i>0: 
       d[t[0]][i-1].append(v) 
    return d 

在你想知道我的背景情況下,元組的列表代表的測量。每個元組中的第一項是被測量事物的標識。 後續項目是該事物的不同類型的度量。事物以隨機順序測量,每次都是未知數。 該功能將每個測量值集中在一起進行進一步處理。隨着應用的發展,不同類型的測量將被添加。 當客戶端代碼中的度量類型數量發生變化時,我希望這個Collat​​e函數不必更改。

+0

如果相同ID的元組包含不同數量的測量結果,例如: ('a',1.0,0.1),('b',2.0,0.2),('a',3.0),('a',4.0,0.4)]應該產生什麼? – void

回答

0

您可以使用itertools.groupby項目首先使用的字母,然後將其添加到相應的字典鍵之前收集屬於使用zip(*...)相同ID的所有測量:

from itertools import groupby, islice 
import operator 

def collate(lst, f=operator.itemgetter(0)): 
    d = {} 
    for k, g in groupby(sorted(lst, key=f), f): 
     d[k] =() 
     for v in islice(zip(*g), 1, None): 
      d[k] += (list(v),) 
    return d 

測試

lst = [('a',), ('b',), ('a',)] 
print(collate(lst)) 
# {'a':(), 'b':()} 

lst = [('a', 1.0), ('b', 2.0), ('a', 3.0)] 
print(collate(lst)) 
# {'a': ([1.0, 3.0],), 'b': ([2.0],)} 

lst = [('a', 1.0, 0.1, 7), ('b', 2.0, 0.2, 8), ('a', 1.0, 0.3, 9)] 
print(collate(lst)) 
# {'a': ([1.0, 1.0], [0.1, 0.3], [7, 9]), 'b': ([2.0], [0.2], [8])} 

我已經避免使用defaultdict,因爲在零測量的情況下(即, [('a',), ('b',), ('a',)])你仍然需要明確地設置鍵值;這打破了這個收藏的目的。

如果您需要處理缺少的測量,請將zip替換爲itertools.zip_longest,並通過明確的fillvalue替換默認的None