2017-08-21 3 views
-1

Python Newbe hier. Ich habe Stack Overflow angeschaut, kann aber keine genau ähnliche Frage finden. Ich versuche, eine Liste von Dicts zusammenzuführen, die den gleichen Schlüssel und die gleichen Werte haben (also in meinem Fall zusammenführen, wo der Name derselbe ist).Wie füge ich Liste von Dicts mit demselben Schlüssel zusammen, wo Werte gleich sind?

Dies ist meine aktuelle Liste:

current = [ 
    {'name' : 'food festival', 'category' : ['Miscellaneous', 'Undefined'], 'venue' : 'venue_1', 'price_1' : 100, 'price_2' : 120, 'start' : '2017-10-04T14:30:00Z'}, 
    {'name' : 'food festival', 'category' : ['Miscellaneous', 'Undefined'], 'venue' : 'venue_2', 'price_1' : 150, 'price_2' : 200, 'start' : '2017-11-04T14:30:00Z'}, 
    {'name' : 'music festival', 'category': ['music', 'pop'], 'venue' : 'venue_3', 'price_1' : 300, 'price_2' : 320, 'start' : '2017-12-04T14:30:00Z'} 
    ] 

Und das ist, was ich zu erreichen versuchen:

final = [ 
    { 
    'name': 'food festival', 
    'category': ['Miscellaneous', 'Undefined'], 
    'shows': [ 
     { 
     'start': '2017-10-04T14:30:00Z', 
     'venue': 'venue_1', 
     'prices': [ 
      { 'price_1' : 100 }, 
      { 'price_2' : 120} 
     ] 
     }, 
     { 
     'start': '2017-11-04T14:30:00Z', 
     'venue': 'venue_2', 
     'prices': [ 
      { 'price_1': 150 }, 
      { 'price_2' : 200 } 
     ] 
     } 
    ] 
    }, 
    { 
    'name': 'music festival', 
    'category': ['music', 'pop'], 
    'shows': [ 
     { 
     'start': '2017-12-04T14:30:00Z', 
     'venue': 'venue_3', 
     'prices': [ 
      { 'price_1' : 300 }, 
      { 'price_2' : 320} 
     ] 
     } 
    ] 
    } 
] 
+0

Ihre Änderung der „Preis“ Schlüssel sieht komplizierter als nur durch Schlüssel verschmelzenden .. Sind Sie sicher, dass Sie wollen, dass "Preise" eine Liste von Einzellängen sind? –

+0

Ja, das wäre das wünschenswerteste Ergebnis - vielleicht hätte ich das im Titel und in der Erklärung etwas deutlicher machen sollen. –

+0

Ich denke wie @IzaakvanDongen, warum verwenden Sie einfach keine Liste und der Index ist der Preis? 'Preise': [300, 320 '] – SD3L

Antwort

1

Hier einige Code:

from pprint import pprint as pp 


current = [ 
    {'name' : 'food festival', 'category' : ['Miscellaneous', 'Undefined'], 'venue' : 'venue_1', 'price_1' : 100, 'price_2' : 120, 'start' : '2017-10-04T14:30:00Z'}, 
    {'name' : 'food festival', 'category' : ['Miscellaneous', 'Undefined'], 'venue' : 'venue_2', 'price_1' : 150, 'price_2' : 200, 'start' : '2017-11-04T14:30:00Z'}, 
    {'name' : 'music festival', 'category': ['music', 'pop'], 'venue' : 'venue_3', 'price_1' : 300, 'price_2' : 320, 'start' : '2017-12-04T14:30:00Z'} 
] 


SPECIAL_EVENT_KEYS = ("name", "category") 
INVALID_INDEX = -1 


def convert_event(event, special_event_keys=SPECIAL_EVENT_KEYS): 
    ret = dict() 
    prices_list = list() 
    for key in event: 
     if key in special_event_keys: 
      continue 
     elif key.startswith("price_"): 
      prices_list.append({key: event[key]}) 
     else: 
      ret[key] = event[key] 
    ret["prices"] = prices_list 
    return ret 


def merge_events_data(events, special_event_keys=SPECIAL_EVENT_KEYS): 
    ret = list() 
    for event in events: 
     existing_index = INVALID_INDEX 
     for idx, obj in enumerate(ret): 
      for key in special_event_keys: 
       if obj[key] != event[key]: 
        break 
      else: 
       existing_index = idx 
     if existing_index == INVALID_INDEX: 
      new_object = dict() 
      for key in special_event_keys: 
       new_object[key] = event[key] 
      new_object["shows"] = [convert_event(event, special_event_keys=special_event_keys)] 
      ret.append(new_object) 
     else: 
      ret[existing_index]["shows"].append(convert_event(event, special_event_keys=special_event_keys)) 
    return ret; 


def main(): 
    merged_events = merge_events_data(current) 
    print("\nResulting object:\n") 
    pp(merged_events) 
    #print("Equal:", merged_events == final) # Commented out to avoid including the contents of 'final' in the answer as it would get too large; add it and decomment for testing purpose 


if __name__ == "__main__": 
    main() 

Hinweise:

  • Der Algorithmus beruht auf der Tatsache, dass, wenn 2 (Eingang) Ereignisse die gleichen Werte für die Schlüssel haben: name und category, Sie werden zusammengeführt (über die shows Liste), andernfalls sind sie separate Einträge in dem zusammengeführten Ergebnis
  • convert_event: nimmt ein Ereignis wie es in der ersten Liste ist und wandelt es in ein Ereignisse für die Ausgabeliste:
    • Streifen aus den name und category Schlüsseln
    • Aggregates prices_* Einträge in einem Wörterbuch als Liste entsprechend den prices Schlüssel
  • merge_events_data: iteriert über die erste Ereignisliste und
    • Wenn die Ereignis nicht in der Ausgabeliste ist (kein Eintrag mit name und category Werten entsprechen), sie schafft
    • Wenn eine solche Ereignis gefunden wird, dessen Inhalt (shows) mit der Augmented Strom Ereignis Daten
  • -Code ist Python3 und Python2 kompatibel
  • Es kann auf jeden Fall sowohl aus Stil und Leistung verbessert werden PoV

Ausgang:

e:\Work\Dev\StackOverflow\q45794604>c:\Install\x64\Python\3.5.3\python.exe a.py 

Merged object: 

[{'category': ['Miscellaneous', 'Undefined'], 
    'name': 'food festival', 
    'shows': [{'prices': [{'price_2': 120}, {'price_1': 100}], 
      'start': '2017-10-04T14:30:00Z', 
      'venue': 'venue_1'}, 
      {'prices': [{'price_2': 200}, {'price_1': 150}], 
      'start': '2017-11-04T14:30:00Z', 
      'venue': 'venue_2'}]}, 
{'category': ['music', 'pop'], 
    'name': 'music festival', 
    'shows': [{'prices': [{'price_2': 320}, {'price_1': 300}], 
      'start': '2017-12-04T14:30:00Z', 
      'venue': 'venue_3'}]}] 
0

Ihre Datenstruktur ein wenig verwirrend ist. Ich nehme an, dass die Eingabe, current, wie es ist, behoben werden muss, aber ich habe final ein bisschen geändert, um klarer zu sein. Ich denke, final in diesem Format wird mehr nutzbar und klarer zu interagieren, obwohl, wenn Sie wirklich wollen, die andere Version von final, lassen Sie es mich wissen.

import pprint 

current = [ 
    {'name' : 'food festival', 'category' : ['Miscellaneous', 'Undefined'], 'venue' : 'venue_1', 'price_1' : 100, 'price_2' : 120, 'start' : '2017-10-04T14:30:00Z'}, 
    {'name' : 'food festival', 'category' : ['Miscellaneous', 'Undefined'], 'venue' : 'venue_2', 'price_1' : 150, 'price_2' : 200, 'start' : '2017-11-04T14:30:00Z'}, 
    {'name' : 'music festival', 'category': ['music', 'pop'], 'venue' : 'venue_3', 'price_1' : 300, 'price_2' : 320, 'start' : '2017-12-04T14:30:00Z'} 
    ] 

final = {} 

for fest in current: 
    name = fest["name"] 
    if name not in final: 
     final[name] = {"category": fest["category"], 
         "shows": []} 

    show = {attr: fest[attr] for attr in ["start", "venue", "price_1", "price_2"]} 

    final[name]["shows"].append(show) 

pprint.pprint(final) 

Dies hat den Ausgang:

{'food festival': {'category': ['Miscellaneous', 'Undefined'], 
        'shows': [{'price_1': 100, 
           'price_2': 120, 
           'start': '2017-10-04T14:30:00Z', 
           'venue': 'venue_1'}, 
          {'price_1': 150, 
           'price_2': 200, 
           'start': '2017-11-04T14:30:00Z', 
           'venue': 'venue_2'}]}, 
'music festival': {'category': ['music', 'pop'], 
        'shows': [{'price_1': 300, 
           'price_2': 320, 
           'start': '2017-12-04T14:30:00Z', 
           'venue': 'venue_3'}]}} 

Hinweis: das dict Verständnis I verwendet wird, kann bis zu einem gewissen Version von Python3 spezifisch sein, ich bin mir nicht sicher. Es kann leicht ersetzt werden

show = dict((attr, fest[attr]) for attr in ["start", "venue", "price_1", "price_2"]) 

ich nicht viel geändert haben - vor allem Finale ist nun ein dict, wo der Name des Festivals einen Schlüssel zum dict ist vertreten, und ich habe immer nur price_1 und price_2 als Schlüssel, da es nur zwei davon gibt, was meiner Meinung nach keine Liste von Wörterbüchern rechtfertigt.

Ein anderer Vorschlag: Anstelle der Zeichenfolge "Undefined" könnten Sie Pythons None Objekt verwenden.

Verwandte Themen