2014-12-26 3 views
11

Ich suche nach ähnlichen Elementen in einer Liste basierend auf den ersten drei Zeichen in der Zeichenfolge. Zum Beispiel:Wie gruppiert man ähnliche Elemente in einer Liste?

test = ['abc_1_2', 'abc_2_2', 'hij_1_1', 'xyz_1_2', 'xyz_2_2'] 

Wie kann ich Gruppe der oben Listenelemente in Gruppen auf der Grundlage der ersten Gruppierung von Buchstaben (z 'abc')? Im Folgenden ist die beabsichtigte Ausgabe:

output = {1: ('abc_1_2', 'abc_2_2'), 2: ('hij_1_1',), 3: ('xyz_1_2', 'xyz_2_2')} 

oder

output = [['abc_1_2', 'abc_2_2'], ['hij_1_1'], ['xyz_1_2', 'xyz_2_2']] 

ich versucht habe itertools.groupby mit diesem ohne Erfolg zu erreichen:

>>> import os, itertools 
>>> test = ['abc_1_2', 'abc_2_2', 'hij_1_1', 'xyz_1_2', 'xyz_2_2'] 
>>> [list(g) for k.split("_")[0], g in itertools.groupby(test)] 
[['abc_1_2'], ['abc_2_2'], ['hij_1_1'], ['xyz_1_2'], ['xyz_2_2']] 

Ich habe sah die folgenden Beiträge ohne Erfolg:

How to merge similar items in a list. Das Beispiel gruppiert ähnliche Elemente (z. B. 'house' und 'Hose'), wobei ein Ansatz verwendet wird, der für mein Beispiel zu kompliziert ist.

How can I group equivalent items together in a Python list?. Hier fand ich die Idee für das Listenverständnis.

Antwort

8

Der .split("_")[0] Teil sollte innerhalb einer einzigen Argumentfunktion sein, die Sie als zweites Argument an itertools.groupby übergeben.

>>> import os, itertools 
>>> test = ['abc_1_2', 'abc_2_2', 'hij_1_1', 'xyz_1_2', 'xyz_2_2'] 
>>> [list(g) for _, g in itertools.groupby(test, lambda x: x.split('_')[0])] 
[['abc_1_2', 'abc_2_2'], ['hij_1_1'], ['xyz_1_2', 'xyz_2_2']] 
>>> 

es im for ... Teil tut nichts, da das Ergebnis sofort verworfen.


Auch wäre es etwas effizienter seine str.partition zu verwenden, wenn Sie nur ein einziges Split wollen:

[list(g) for _, g in itertools.groupby(test, lambda x: x.partition('_')[0])] 

Demo:

>>> from timeit import timeit 
>>> timeit("'hij_1_1'.split('_')") 
1.3149855638076913 
>>> timeit("'hij_1_1'.partition('_')") 
0.7576401470019234 
>>> 

Das ist kein großes Problem, wie Beide Methoden sind bei kleinen Saiten ziemlich schnell, aber ich dachte, ich würde es erwähnen.

+0

Danke, das funktioniert super. Ich habe kürzlich festgestellt, dass es eine gute Vorgehensweise ist, sicherzustellen, dass die Eingabeliste z. 'test = sortiert (['abc_1_2', 'abc_2_2', 'hij_1_1', 'xyz_1_2', 'xyz_2_2'])' '. Andernfalls, wenn die Eingabeliste nicht sortiert ist, funktioniert 'iertools.groupby' nicht wie erwartet. – Borealis

+1

Ja, das Sortieren der Liste ist eine gute Übung, wenn Sie 'itertools.groupby' verwenden. Dies liegt daran, dass 'groupby' nur Läufe mit ähnlichen Werten erfasst. Das heißt, es kann etwas fehlen, wenn die Liste nicht sortiert ist. Ich habe das in meinem Beitrag nicht erwähnt, weil das Hauptaugenmerk auf der Verwendung von 'groupby' lag und auch Ihre Liste bereits sortiert war. – iCodez