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

タプルのリストは、タプルの長さが不明なタプルリストの辞書に照合しますか?

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

を生成

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

を生成し

{'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])} 

Iゼロの場合(すなわち、ゼロの場合)にはdefaultdictの使用を避けている。 [('a',), ('b',), ('a',)])でも、キー値を明示的に設定する必要があります。そのコレクションの目的を破るものです。

欠落した測定値を処理する必要がある場合は、zipitertools.zip_longestに置き換えて、fillvalueをデフォルトのNoneに置き換えて明示的に渡します。

関連する問題