2016-08-03 7 views
4

Erstplakat hier. Wenn ich eine Liste mit Unterlisten mit verschiedenen Informationen habe und alle Unterlisten mit demselben Schlüsselwert in einer neuen Unterliste gruppieren möchte (z. B. unique-ify eine Liste basierend auf den Schlüsselwerten), was ist der effizienteste Weg? Dies?Der effizienteste Weg, Python-Liste in Unterlisten über Schlüssel zu brechen, während die Reihenfolge beibehalten wird

Beispiel:

A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]] 

Und ich möchte alle Teil-Listen zu gruppieren, die denselben Eintrag in der '0' Index in eine neue sublist, vorzugsweise die ursprüngliche Ordnung zu bewahren:

B = [ [[1,2,3], [1,3,7], [1,2,4]], [[2,1,3],[2,3,8]], [[8,9,6]], [[3,7,9]] ] 

I Ich habe dieses Problem schon oft gelöst, aber ich würde gerne sehen, ob es einen effizienteren Weg gibt, dies zu tun. Ja, ich könnte das numpy-Paket aus diesem Grund verwenden, aber ich bin an der Listenlösung interessiert.

Normalerweise würde ich zunächst das Element im ersten Index in jeder Unterliste (mit der Set-Methode, wenn ich nicht um Effizienz oder Ordnung kümmern), dann Schleife über die gesamte Liste, Kombinieren von Unterlisten in eine neue sublist:

def getUniqueList(list): 
    seen = [] 
    for e in list: 
     if e not in seen: 
     seen.append(e) 
    return seen 

def uniquify(list): 
    # Get all items from the first column 
    new_list = [item[0] for item in list] 
    return getUniqueList(new_list) 

def rearrangeList(A, A_0): 
    B = [] 
    for i in range(len(A_0)): 
     B.append([]) 
    for i in range(len(A)): 
     index = A_0.index(A[i][0]) 
     B[index].append(A[i]) 
    return B 

A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]] 
A_0 = uniquify(A) # Contains all unique keys in index 0 of list A 
B = rearrangeList(A, A_0) 
print(B) 

diese sollte (ich das nicht testen haben, aber das ist, wie ich es wäre Code) führen:

B = [[[1,2,3] , [1,3,7], [1,2,4]], [[2,1,3], [2,3,8]], [[8,9,6]], [[3, 7,9]]]

Ich wollte wissen, ob 1) es einen besseren Weg gibt, dies in Bezug auf Effizienz zu tun, und 2) gibt es eine Möglichkeit, dies in weniger Schritten zu tun (nicht unbedingt effizient, nur neugierig). Hoffentlich wird diese Frage gut gestellt, aber lassen Sie mich wissen, wenn es bearbeitet werden muss!

+2

Die besten Leute, die Verbesserungen am Arbeitscode vorschlagen, verwenden http://codereview.stackexchange.com anstelle von stackoverflow. –

+1

Wenn Sie die Reihenfolge der Gruppen beibehalten, unterscheidet sich diese Frage von dem einfachen Gruppierungsproblem. Beachten Sie, dass das Hinzufügen eines "Sortierten" zu der resultierenden Liste nicht die Sortierung wie in der Frage angefordert erstellt. – topkara

+0

@ TadhgMcDonald-Jensen, danke, ich werde es das nächste Mal versuchen! – rlarson

Antwort

2

Im Wesentlichen möchten Sie eine Gruppierungsoperation. Verwenden Sie ein Wörterbuch zu einer Gruppe von Tasten, benutzen Sie OrderedDict um perserve:

>>> from collections import OrderedDict 
>>> groups = OrderedDict() 
>>> A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]] 
>>> key = lambda l: l[0] 
>>> for sub in A: 
... groups.setdefault(key(sub),[]).append(sub) 
... 
>>> groups 
OrderedDict([(1, [[1, 2, 3], [1, 3, 7], [1, 2, 4]]), (2, [[2, 1, 3], [2, 3, 8]]), (8, [[8, 9, 6]]), (3, [[3, 7, 9]])]) 
>>> B = list(groups.values()) 
>>> B 
[[[1, 2, 3], [1, 3, 7], [1, 2, 4]], [[2, 1, 3], [2, 3, 8]], [[8, 9, 6]], [[3, 7, 9]]] 
+0

warum nicht 'B = list (groups.values ​​())' ?? – Copperfield

+0

@Copperfield oh ich war nur dumm. –

+0

@ juanpa.arrivillaga, das hat enorm geholfen, danke! – rlarson

-1

Eine alte Schule (aber gut und einfach) Ansatz:

A = [[1,2,3], [1,3,7], [2,1,3], [8,9,6], [3,7,9], [2,3,8], [1,2,4]] 
A = sorted(A, key=lambda x: x[0]) #sort just by the first index to preserve order 
B = [[A[0]]] 

for list in A[1:]:    # add to the last list or create new one 
    if B[-1][-1][0]==list[0]: # 
     B[-1].append(list)  # 
    else:      # 
     B.append([list])  # 

B 
#output: 
[[[1, 2, 3], [1, 3, 7], [1, 2, 4]], [[2, 1, 3], [2, 3, 8]], [[3, 7, 9]], [[8, 9, 6]]] 
1

Die Forderung nach der Reihenfolge der ursprünglichen Liste zu bewahren ist interessant.

Unter der Annahme, dass Ihre Liste A ist und Sie das Ergebnis in B, der folgende Code erstellt die Liste, da sie die Eingabe verbraucht, daher die ursprüngliche Reihenfolge der Liste erhalten sind:

from collections import defaultdict 
B=[] 
reduce(lambda a,n: a[n[0]].append(n) or a,A,defaultdict(lambda: B.append([]) or B[-1])) 

oder die folgende einfacher Code erstellt die Liste innerhalb defaultdict und kopiert dann vorbei, aber die Reihenfolge der ursprünglichen Liste verloren:

from collections import defaultdict 
B=reduce(lambda a,n: a[n[0]].append(n) or a,A,defaultdict(list)).values() 

Beachten sie, dass die Teil-Listen in der Reihenfolge ursprünglich erscheinen sie sein wird.