2016-04-08 6 views
3

Ich habe eine Liste von Dicts unten gezeigt, ich möchte einige Dicts in einem basierend einige Schlüssel/Wert-Paar zusammenführen.Merge dicts aus einer Liste von Dicts basierend auf einem Schlüssel/Wert-Paar

[ 
    {'key': 16, 'value': 3, 'user': 3, 'id': 7}, 
    {'key': 17, 'value': 4, 'user': 3, 'id': 7}, 
    {'key': 17, 'value': 5, 'user': 578, 'id': 7}, 
    {'key': 52, 'value': 1, 'user': 3, 'id': 48}, 
    {'key': 46, 'value': 2, 'user': 578, 'id': 48} 
] 

Nun, wie Sie dict 1 & 2 haben dieselben Werte für Benutzer & id Tasten sehen. So ist es möglich, diese beiden dicts wie

[ 
    {'key': [16,17], 'value': [3,4], 'user': 3, 'id': 7}, 
    {'key': [17], 'value': [5], 'user': 578, 'id': 7}, 
    {'key': [52], 'value': [1], 'user': 3, 'id': 48}, 
    {'key': [46], 'value': [2], 'user': 578, 'id': 48} 
] 

zu verschmelzen bedeutet user & id Wert eindeutig together.What die effiziente Art und Weise wird sein müssen zu fusionieren (wenn möglich)

+0

Warum Listen in gemischten Wörterbüchern? – Peaceful

+0

@SnehalShekatkar, so dass ich Werte von beiden fusionierten dicts für 'Schlüssel & Wert' habe. Wenn Sie einen besseren Ansatz kennen, gibt es kein Problem. – user5594493

+0

Ich denke, Sie sollten dann haben 'Schlüssel: [16, 17]' anstelle von '[17, 4]' – Peaceful

Antwort

2

Funktion Im Anschluss an die Liste der Wörterbücher konvertieren neues Format:

def convert(d): 
    res = {} 
    for x in d: 
     key = (x['user'], x['id']) 
     if key in res: 
      res[key]['key'].append(x['key']) 
      res[key]['value'].append(x['value']) 
     else: 
      x['key'] = [x['key']] 
      x['value'] = [x['value']] 
      res[key] = x 

    return res.values() 

Es mutiert die ursprünglichen Wörterbücher und die Reihenfolge der Wörterbücher im Ergebnis wird zufällig sein. Wenn an den Eingang angelegt wird es folgendes Ergebnis produzieren:

[ 
    {'id': 7, 'value': [5], 'key': [17], 'user': 578}, 
    {'id': 7, 'value': [3, 4], 'key': [16, 17], 'user': 3}, 
    {'id': 48, 'value': [1], 'key': [52], 'user': 3}, 
    {'id': 48, 'value': [2], 'key': [46], 'user': 578} 
] 
+0

Thx viel. Eine allgemeine Frage. Nehmen wir an, wir haben eine Liste von Diktaten zwischen 1000 und 10000. Die Konvertierung, die ich wünsche, wird Zeit brauchen und immer Leistungsprobleme haben, daran besteht kein Zweifel. Aber was denkst du wie viel Zeit es braucht. – user5594493

+0

Ich testete mit 1000000 dicts durch das Kopieren Ihrer Eingabe 200000 mal, die Funktion lief weniger als 1 Sekunde auf meinem Laptop. Mit den Zahlen, die du angegeben hast, würde ich mir über die Leistung keine Sorgen machen. – niemmi

0

Sie Aggregatfunktion folgende verwenden:

def aggregate(lst): 
    new = {} 
    for d in lst: 
     new.setdefault((d['user'], d['id']), []).append(d) 
    for k, d in new.items(): 
     if len(d) > 1: 
      keys, values = zip(*[(sub['key'], sub['value']) for sub in d]) 
      user, id_ = k 
      yield {'key': keys, 'value': values, 'user': user, 'id': id_} 
     else: 
      yield d[0] 

print list(aggregate(lst)) 
[{'id': 7, 'value': 5, 'key': 17, 'user': 578}, 
{'id': 7, 'value': (3, 4), 'key': (16, 17), 'user': 3}, 
{'id': 48, 'value': 1, 'key': 52, 'user': 3}, 
{'id': 48, 'value': 2, 'key': 46, 'user': 578}] 
+0

Es wird nicht funktionieren! Sie haben "aggregate" am Ende des Codes falsch gesetzt! – TheRandomGuy

2

Lassen dicts Ihre ursprüngliche Liste der Wörterbücher sein. Diese Idee bildet eindeutige Kombinationen von Benutzer und ID zu defaultdict(list) Objekten ab. Das Endergebnis ist die Liste der Werte aus diesem Wörterbuch.

from collections import defaultdict 
tmp = defaultdict(dict) 

for info in dicts: 
    tmp[(info['user'], info['id'])].setdefault('key', []).append(info['key']) 
    tmp[(info['user'], info['id'])].setdefault('value', []).append(info['value']) 

for (user, id_), d in tmp.items(): # python2: use iteritems 
    d.update(dict(user=user, id=id_)) 

result = list(tmp.values()) # python2: tmp.values() already gives a list 
del tmp 
+0

Vielen Dank. Wie du sehen kannst, hat @niemmi auch meine Frage beantwortet. Aber mir geht es mehr um Leistung. Und ich weiß nicht, welcher eine bessere Leistung haben wird. was denkst du ? Sie können auf meinen Kommentar auf niemi Frage beziehen. – user5594493

+0

@ user5594493 Ich denke, die Leistung wird ähnlich sein. Warum versuchst du es nicht mit dem Modul 'timeit'? – timgeb

+0

Thx werde ich tun. Zwischen den Kollektionen ist der Zauber beim Import falsch. – user5594493

Verwandte Themen