2016-04-15 9 views
2

I 2-Arrays in Python zusammenführen möchten und Werte hinzufügen, basierend auf einem SchlüsselMerge-Arrays und in Python basierend auf Schlüssel hinzufügen

Beispiel:

Groceries = [] 
A = [{group: 'Fruit', 
     item: 'Banana', 
     quantity: 10}, 
    {group: 'Vegetable', 
     item: 'Carrot', 
     quantity: 1}] 
for item in A: 
    Groceries.append(item) 
B = [{group: 'Fruit', 
     item: 'Banana', 
     quantity: 3}, 
    {group: 'Vegetable', 
     item: 'Celery', 
     quantity: 1}] 
for item in B: 
    Groceries.append(item) 

print (Lebensmittel) kehrt:

[{group: 'Fruit', 
    item: 'Banana', 
    quantity: 10}, 
    {group: 'Vegetable', 
    item: 'Carrot', 
    quantity: 1}, 
    {group: 'Fruit', 
    item: 'Banana', 
    quantity: 3}, 
    {group: 'Vegetable', 
    item: 'Celery', 
    quantity: 1}] 

gibt es eine Möglichkeit, sie in einer Weise zusammenführen können, wo das Ergebnis stattdessen würde:

[{group: 'Fruit', 
    item: 'Banana', 
    quantity: 13}, 
{group: 'Vegetable', 
    item: 'Carrot', 
    quantity: 1}, 
{group: 'Vegetable', 
    item: 'Celery', 
    quantity: 1}] 

(Beachten Sie, dass es 13 Bananen statt 2 Instanzen von Bananen Zustände)

+0

Wenn Sie diesen Algorithmus ausführen möchten, wäre es besser, Ihre Daten anders zu strukturieren. –

+1

Auch eine Tomate ist keine Karotte. –

+0

Was würden Sie für die Struktur empfehlen? Und du hast mich. Ich werde das Gemüse reparieren :) –

Antwort

0

Am ineffizienten Weg wäre es, die Liste für ein vorhandenes Wörterbuch zu suchen, passend zu dem 'group' und 'item':

for item in B: 
    existing = next((existing for existing in Groceries 
        if existing['group'] == item['group'] and 
        existing['item'] == item['item']), 
        None) 
    if existing: 
     existing['quantity'] += item['quantity'] 
    else: 
     Groceries.append(item) 

Dies ist ineffizient, da next verwendet wird, um eine lineare Suche durch alle Einträge in Lebensmittel zu machen. Wenn du Millionen von Gegenständen hättest, würde es sehr langsam werden.

Wenn Sie Ihre Daten so umstrukturieren, dass sie auf Gruppen und Elementen basieren, ist das viel schneller. Sie benötigen ein Wörterbuch von Wörterbüchern. Sie können auch haben ein defaultdict automatisch Wert verwenden 0 für fehlende Einzelteile:

from collections import defaultdict 

defaultitems = lambda: defaultdict(int) 
quantities = defaultdict(defaultitems) 

Dies ermöglicht Ihnen, Gruppen und Einzelteile mit Quantität erstellen 0:

defaultitems = lambda: defaultdict(int) 
quantities = defaultdict(defaultitems) 

for item in A: 
    quantities[item['group']][item['item']] = item['quantity'] 
:

>>> quantities['Fruit']['Tomato'] 
0 

Erste a Erstellen Sie

Dann fügen Sie hinzu B:

for item in B: 
    quantities[item['group']][item['item']] += item['quantity'] 

Da Sie jedoch den Standard bekommen hinzufügen Sie könnten A und B alle in einer Schleife, indem sie miteinander verketten (mit chain):

from itertool import chain 

for item in chain(A, B): 
    quantities[item['group']][item['item']] += item['quantity'] 
+0

Können Sie diese Antwort erweitern? Insbesondere, wo ich angeblich 'defaultquantities = defaultdict (int) default = defaultdict (defaultquantities) defaultgroups = defaultdict (default)' –

+0

Apologies zu verwenden, habe ich die Deklaration des Standard dict vermasselt. Das bringt mir bei, den Code zu schreiben, ohne ihn zuerst zu testen. –

0

Verwenden Sie ein Unterstützungsverfahren die Zusammenführung zu tun und ein Wörterbuch verwenden, um Speichern Sie die Ergebnisse. Dies wird tun, was Sie wollen, aber es wird die Reihenfolge der Liste verlieren. Ich bin mir nicht sicher, ob du das brauchst.

Groceries = {} 
A = [{'group': 'Fruit', 
     'item': 'Banana', 
     'quantity': 10}, 
    {'group': 'Vegetable', 
     'item': 'Carrot', 
     'quantity': 1}] 

for item in A: 
    Groceries[item['item']] = item 

B = [{'group': 'Fruit', 
     'item': 'Banana', 
     'quantity': 3}, 
    {'group': 'Vegetable', 
     'item': 'Celery', 
     'quantity': 1}] 

def add_item(d, other): 
    key = other['item'] 
    if d[key] in d: 
     d[key]['quantity'] += y['quantity'] 
    else: 
     d[key] = y 

for item in B: 
    add_item(Groceries, item) 

print(Groceries.values()) 

[{ 'Gruppe': 'Früchte', 'Menge': 13, 'item': 'Banana'}, { 'Gruppe': 'pflanzlich', 'Menge': 1, 'item': 'Sellerie'}, { 'Gruppe': 'pflanzlich', 'Menge': 1, 'item': 'Möhre'}]

2

Für Jobs zu zählen, verwenden Sie einen Counter:

from collections import Counter 

c = Counter() 

Der Zähler braucht die richtigen Tasten, um sich zu unterscheiden zieren Elemente bilden so (group, item) Tupel von Ihrem ursprünglichen dict Format als Schlüssel, die Menge als Wert:

c.update({(d["group"], d["item"]): d["quantity"] for d in A}) 
c.update({(d["group"], d["item"]): d["quantity"] for d in B}) 

Diese Methode einen Nachteil hat jedoch: Wenn Ihre Liste A oder B mehrere Datensätze für die gleiche Position enthält, wird dies nicht funktionieren richtig, da das Wörterbuchverständnis nur das letzte "erinnert". Wenn Sie wissen, dass dies eine Möglichkeit ist, können Sie auf Ebene zurückkehren alt for-Schleifen und Addition:

from operator import itemgetter 
from itertools import chain 

keymaster = itemgetter("group", "item") 
for d in chain(A, B): 
    c[keymaster(d)] += d["quantity"] 

um Ihr ursprüngliches Format wieder eine Liste von kleinen Wörterbücher von dem Thekenartikel erstellen:

[{"group": k[0], "item": k[1], "quantity": v} for k, v in c.items()] 

# results 
[{'item': 'Carrot', 'group': 'Vegetable', 'quantity': 1}, 
{'item': 'Celery', 'group': 'Vegetable', 'quantity': 1}, 
{'item': 'Banana', 'group': 'Fruit', 'quantity': 13}] 
0
Groceries = [] 
A = [{'group': 'Fruit', 
     'item': 'Banana', 
     'quantity': 10}, 
    {'group': 'Vegetable', 
     'item': 'Carrot', 
     'quantity': 1}] 
for item in A: 
    Groceries.append(item) 
B = [{'group': 'Fruit', 
     'item': 'Banana', 
     'quantity': 3}, 
    {'group': 'Vegetable', 
     'item': 'Celery', 
     'quantity': 1}] 
for item in B: 
    Groceries.append(item) 
new_data = [] 
for i in Groceries: 
    yes = False 
    for s in new_data: 
     if s['item'] == i['item']: 
      s['quantity'] += i['quantity'] 
      yes = True 
    if not yes: 
     new_data.append(i) 
print new_data 

Sie können die Liste durchlaufen und die Menge hinzufügen, wenn ein Wert vorhanden ist. Dies kann helfen

Verwandte Themen