2016-11-20 3 views
0

Ich habe folgende einfache Datenstrukturen:Wie kann man zwei Listen von Wörterbüchern in Python verbinden?

teams = [ { 'league_id': 1, 'name': 'Kings' }, { 'league_id': 1, 'name': 'Sharkls' }, { 'league_id': 2, 'name': 'Reign' }, { 'league_id': 2, 'name': 'Heat' } ] 
leagues = [ { 'league_id': 1, 'name': 'League 1' }, { 'league_id': 2, 'name': 'League 2' } ] 

Und ich habe folgendes dict Verständnis:

league_teams = { x['league_id']: [ t['name'] 
    for t in teams if t['league_id'] == x ['league_id'] ] 
    for x in leagues } 

Welche ergibt:

{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']} 

Gibt es einen einfacheren Weg, mit itertools oder etwas, um dieses Diktat zu bekommen? Das fühlt sich ein wenig beschwerlich an.

+0

Ist es notwendig, suchen in den 'Ligen'? Willst du nicht: 'league_teams = {x ['name']: [t ['name'] für t in Teams wenn t ['league_id'] == x ['league_id']] für x in Ligen } '? –

+0

* Das fühlt sich ein wenig umständlich an ... ... das könnte bei StackOverflow ein Thema sein, da wir Fehler bei Code beheben, der nicht funktioniert. Erwägen Sie, auf [CodeReview] (http://codereview.stackexchange.com/) zu posten. Ehrlich gesagt, sehe ich kein Problem mit Code. – Parfait

Antwort

1

Sie brauchen hier nicht itertools, stattdessen ist collections.defaultdict die bessere Wahl. Die Komplexität Ihrer Lösung ist O (n * m), während sie mit defaultdict O (n + m) ist.

können Sie erreichen, was Sie gerne möchten:

from collections import defaultdict 

# create set to store `league_id` in `leagues`. Set holds unique 
# values and also searching in set is faster than in normal list 
leagues_id = set([item['league_id'] for item in leagues]) 

my_dict = defaultdict(list) 

for item in teams: 
    if item['league_id'] in leagues_id: 
     my_dict[item['league_id']].append(item['name']) 

wo am Ende my_dict den Wert halten wird:

{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']} 

Edit: Falls Sie auch die Eingabe für die in my_dict wollen league_id vorhanden in Ligen, aber nicht in Teams, müssen Sie explizit Einträge machen wie:

for leagues_id in leagues_ids: 
    _ = my_dict[leagues_id] # Will create empty list for such ids 
+0

Gute Lösung, obwohl eine Sache, die es nicht tun wird, leere Ligen aufzeichnet (Ligen, die einen Namen und eine ID haben, für die aber keine Teams existieren). Der OP-Code zeichnet sie als leere Listen auf, die einer Liga-ID zugeordnet sind. – jez

+0

Ich denke, Sie würden wissen, wie man das in meinem aktuellen Code ändern kann :) –

+0

Herausforderung akzeptiert-siehe meine Antwort. – jez

0

Überprüfung t['league_id'] == x['league_id'] sieht nicht notwendig.

können Sie vereinfachen mit:

import collections 

league_teams = collections.defaultdict(list) 
for t in teams: 
    league_teams[t['league_id']].append(t['name']) 

Wenn Sie itertools für das wirklich:

import itertools 

league_teams = {k: [t['name'] for t in g] 
       for k, g in itertools.groupby(teams, key=lambda t: t['league_id'])} 

Aber es wird nur funktionieren, wenn die Teams Liste sortiert ist.

0

Hier ist eine Anpassung von Moinuddin Quadri O (n + m) -Lösung, die den Fall "leere Liga" abfängt, und die übrigens keine Module importiert werden muss. Die dict output tut double-duty als seine league_ids Satz, und da es vorinitialisiert ist, es muss nicht ein sein collections.defaultdict:

output = { league['league_id']:[] for league in leagues } 
for team in teams: 
    if team['league_id'] in output: 
     output[team['league_id']].append(team['name']) 
print(output) 

Die Ausgabe lautet:

{1: ['Kings', 'Sharkls'], 2: ['Reign', 'Heat']}

+0

Ich vermute, ein "Sharkl" ist ein kleiner bayerischer Hai. – jez

+1

Ja, es wird funktionieren, aber auch hier wird die Komplexität (m + (n * m)) sein, weil 'if' intern die Liste iteriert, um eine Prüfung zu machen –

+0

Um das' if' zu vermeiden, könnte stattdessen 'try '...' außer KeyError: pass 'um das 'append' herum. Aber ich denke, diese O() - Berechnungen lassen in allen Fällen auch die dict key lookup aus. – jez

Verwandte Themen