2016-07-20 14 views
0

を理解:Pythonのリスト、私はリストを含む辞書のリストを持っている

a = [{'alpha': 'a', 'val': 10, 'num': ['one', 'two']}, 
    {'alpha': 'b', 'val': 22, 'num': ['two']}, 
    {'alpha': 'c', 'val': 1, 'num': ['seven']}, 
    {'alpha': 'a', 'val': 10, 'num': ['three','nine']}, 
    {'alpha': 'b', 'val': 9, 'num': ['two', 'four']}] 

私が欲しいの出力は次のようになります。

[{'alpha': 'a', 'TotalVal': 20, num: ['one', 'two', 'three', 'nine'], 'numlen': 4}, 
{'alpha': 'b', 'TotalVal': 31, num: ['two', 'four'], 'numlen': 2}, 
{'alpha': 'c', 'val': 1, 'num': ['seven'], 'numlen': 1}] 

私は次のことを試してみました:

sumVal = collections.defaultdict(float) 
for info in a: 
    sumVal[info['alpha']] += info['val'] 

sumVal = [{'alpha': c, 'TotalVal': sumVal[c]} for c in sumVal] 

numList = collections.defaultdict(list) 
for info in a: 
    numList[info['alpha']].append(info['num']) 
numList = [{'alpha': k, 'num': set(v), 'len': len(set(v))} for k, v in numList.items()] 

def merge_lists(l1, l2, key): 
    merged = {} 
    for item in l1+l2: 
     if item[key] in merged: 
      merged[item[key]].update(item) 
     else: 
      merged[item[key]] = item 
    return [val for (_, val) in merged.items()] 

final = merge_lists(sumVal, numList, 'alpha') 

numListの出力が得られません。次のエラーを取得します。

TypeError: unhashable type: 'list'

希望の出力をより少ないステップで取得してエラーを取り除くにはどうすればよいですか?

+1

の可能性のある重複した[Pythonの辞書:TypeError例外:非ハッシュタイプ: 'リスト'](http://stackoverflow.com/questionsここに私が思い付いた最も簡単な解決策です/ 8532146/python-dictionary-typeerror-unhashable-type-list) –

+1

あなたの正しい出力は何かを説明できますか?また、あなたの質問に完全なトレースバックを表示 –

+0

@joelgoldstick私はそれを言及している、上から2番目のリストは、最終的な出力でなければなりません。 – Blabber

答えて

1

このコードを試してみてください。問題はこのラインである

a = [{'alpha':'a','val':10,'num':['one','two']},{'alpha':'b','val':22,'num':['two']},{'alpha':'c','val':1,'num':['seven']},{'alpha':'a','val':10,'num':['three','nine']},{'alpha':'b','val':9,'num':['two','four']}] 

def merge_dicts(x, y): 
    x.update(y) 
    return x 

def r(acc, x): 
    if x['alpha'] in acc: 
     acc[x['alpha']]['TotalVal'] += x['val'] 
     acc[x['alpha']]['num'] |= set(x['num']) 
     acc[x['alpha']]['numlen'] = len(acc[x['alpha']]['num']) 
    else: 
     acc[x['alpha']] = { 
      'TotalVal': x['val'], 
      'num': set(x['num']), 
      'numlen': len(set(x['num'])), 
     } 
    return acc 

result = map(lambda (x, y): merge_dicts({'alpha': x}, y), 
      reduce(r, a, {}).iteritems()) 
print(result) 
+0

numのものは、私に別個の値(set)を与え、numlenは最終出力のセットの長さを与えるべきです。しかしコードは良いスタートだ。ありがとう:) – Blabber

+0

あなたのコードにはどのような変更を加えることができますか? '{' alpha ':' a '、' TotalVal ':20、' num ':set([' three '、' nine '、' two '、' one '])の出力を返します。 – Blabber

+0

@frist、 'numlen':1}、{'alpha': 'b'}、 'numlen':4}、{'alpha': 'c'、 'TotalVal' 、 'TotalVal':31、 'num':set(['four'、 'two'])、 'numlen':2}]。 - セット内の1つの要素(すべてのリスト)! –

1

numList[info['alpha']].append(info['num']) 

リストにリストを追加するには、あなたがに追加されているリスト内で追加されているリストを置きます。

あなたが望むものは伸びていると思います。

append vs. extend

+0

Extendは望ましい出力を与えません。それを試みた! – Blabber

+0

extendを使用すると、正しいデータがすべてそこにあります。しかし、それはあなたの予想される出力とは異なる順序にあります。辞書は発注されていないことを忘れないでください。 – beauxq

+0

この例では動作しますが、何らかの理由で他のものでは動作しません。 – Blabber

1
#!/usr/bin/env python 

a = [{'alpha':'a','val':10,'num':['one','two', 'one', 'two']},{'alpha':'b','val':22,'num':['two']},{'alpha':'c','val':1,'num':['seven']},{'alpha':'a','val':10,'num':['three','nine']},{'alpha':'b','val':9,'num':['two','four']}] 


def merge_lists(src, key): 
    merged = {} 
    for i in src: 
     _key = i[key] 
     if _key in merged: 
      merged[_key]['TotalVal'] += i['val'] 
      merged[_key]['num'].extend(i['num']) 
      merged[_key]['num'] = list(set(i['num'])) 
      merged[_key]['numlen'] = len(merged[_key]['num']) 
     else: 
      merged[_key] = {'TotalVal': i['val'], 'alpha': i['alpha'], 'num': i['num'], 'numlen': 1} 

    return [val for (_, val) in merged.items()] 


final = merge_lists(a, 'alpha') 

print(final) 

出力: [{ 'α': 'A'、 'TotalVal':20 'NUM':[ '9'、 '3']、 'numlen':2 1、 'num':['seven']、 'numlen':1}、{'alpha': 'b'、 'TotalVal':31、 '}'、{'アルファ': 'c' NUM ':[' 4」、 '2']、 '' numlen:2}]

+0

最後のnumはnumlenをb 2にする別個のエントリを含んでいなければなりません。 – Blabber

+0

あなたのコードにはどのような変更を加えることができますか? – Blabber

+1

@Blabber、重複を削除するには 'list(set(i [' num ']))'を使います。 –

1

などの他の回答として短いが単純ではなく、その実装に

a = [{'alpha':'a','val':10,'num':['one','two']}, 
    {'alpha':'b','val':22,'num':['two']}, 
    {'alpha':'c','val':1,'num':['seven']}, 
    {'alpha':'a','val':10,'num':['three','nine']}, 
    {'alpha':'b','val':9,'num':['two','four']}] 

new_list = [] 

# Loop through entries 
for entry in a: 
    # Store first entries 
    if entry['alpha'] not in [i['alpha'] for i in new_list]: 
     new_dict = {'alpha': entry['alpha'], 
        'TotalVal': entry['val'], 
        'num': entry['num'], 
        'numlen': len(entry['num'])} 
     new_list.append(new_dict) 
     continue 

    # Add in additional entries 
    for i, n in enumerate(new_list): 
     if n['alpha'] == entry['alpha']: 
      entry_vals = entry.values() 
      new_list[i]['TotalVal'] = new_list[i]['TotalVal'] + entry['val'] 
      new_list[i]['num'] = new_list[i]['num'] + entry['num'] 
      new_list[i]['numlen'] = len(new_list[i]['num']) 

# filter final data 
for i, n in enumerate(new_list): 
    # Remove duplicate entries in num 
    for entry in n['num']: 
     if n['num'].count(entry) > 1: 
      new_list[i]['num'].remove(entry) 

    # Update numlen 
    new_list[i]['numlen'] = len(new_list[i]['num']) 

print new_list 
1

a = [{'alpha':'a','val':10,'num':['one','two']}, 
    {'alpha':'b','val':22,'num':['two']}, 
    {'alpha':'c','val':1,'num':['seven']}, 
    {'alpha':'a','val':10,'num':['three','nine']}, 
    {'alpha':'b','val':9,'num':['two','four']}] 

a2 = [] 
alphas = set(d['alpha'] for d in a) 
for alpha in alphas: 
    TotalVal, num, numlen = 0, set(), 0 
    for d in a: 
     if d['alpha'] == alpha: 
      TotalVal += d['val'] 
      num = num | set(d['num']) 
      numlen += 1 
    new_dict = {'alpha': alpha, 'num': list(num), 'numlen': numlen} 
    if numlen > 1: 
     new_dict['TotalVal'] = TotalVal 
    else: 
     new_dict['val'] = TotalVal 
    a2.append(new_dict) 

デモ:

>>> for d in a2: print(d) 
{'alpha': 'a', 'num': ['three', 'nine', 'two', 'one'], 'numlen': 2, 'TotalVal': 20} 
{'alpha': 'c', 'num': ['seven'], 'numlen': 1, 'val': 1} 
{'alpha': 'b', 'num': ['four', 'two'], 'numlen': 2, 'TotalVal': 31} 
関連する問題