2016-07-15 8 views
1

Ich habe einige Schwierigkeiten, eine effiziente Möglichkeit zu finden, eine Liste von Strings zu nehmen und sie in Tupel-Paare umzuwandeln. Ich habe eine Liste ähnlich wie:Python-Liste von Strings zu Tuple-Paaren

listOfNames = ['red-l','blue-l','green-s','red-s','blue-s'] 

Jede Farbe in diesem Beispiel (rot, blau und grün) ist entweder mit einem ‚-l‘ oder ‚es‘ Eintrag oder beides. Ich brauche diese Liste von Strings in Tupel Paare zu konvertieren, wie:

tupleOfNames = [('red-l','red-s'),(None,'green-s'),('blue-l','blue-s')] 

Ich denke, reguläre Ausdrücke gebraucht wird, aber ich bin nicht sicher, wie dies zu tun. Jede Hilfe wird sehr geschätzt. Danke

+0

Wie lange ist die Liste – GMarsh

+0

Die Liste sollte nie mehr als ~ 10 Tausend Einträge sein. – bsheehy

Antwort

3

Eine mögliche Lösung, können wir die Liste sortieren zunächst und dann die Farbe Teil jeder Begriff GROUPBY und jede Gruppe in ein Tupel verwandeln, wenn es enthält nur ein Element eines Keine einfügen in dem Tupel:

import re 
from itertools import groupby 

li = [] 
listOfNames.sort() 
for k, g in groupby(listOfNames, lambda s: re.findall("(.*)-", s)): 
    liG = list(g) 
    if len(liG) == 1: 
     li.append((None, liG[0])) 
    else: 
     li.append(tuple(liG)) 

li 
# [('blue-l', 'blue-s'), (None, 'green-s'), ('red-l', 'red-s')] 
-3

Überprüfen Sie die itertools.product() Funktion. Dies gibt das kartesische Produkt zweier Listen zurück. In Ihrem Fall könnten Sie tun,

from itertools import product 

l_names = ['red-l', 'blue-l'] 
s_names = ['red-s', 'blue-s', 'green-s'] 

tupleOfNames = list(product(l_names, s_names)) 
+0

aber das geht davon aus, dass das OP zwei oder mehr Listen hat. Was ist, wenn (wie in der Frage) nur eine Liste mit vielen verschiedenen Strings vorhanden ist? – marcusshep

+0

Dies ist eine einfache Lösung, die auf dem von dem OP bereitgestellten Anwendungsbeispiel basiert. Ich überlasse es dem OP zu entscheiden, ob er einen flexibleren Ansatz benötigt. – Danny

+1

OP benötigt kein kartesisches Produkt. Sehen Sie sich die Beispielausgabe an. Du gibst 6 Tupel, Sample ist 3. –

0

ich schrieb diese Funktion, die bei weitem nicht perfekt, aber liefert das Ergebnis die Sie sich wünschen:

def tupleofnames(listofnames): 
     result = [] 
     colors = set([x[:-2] for x in listOfNames])  
     for c in colors:   
      if c+"-l" in listofnames: 
       if c+'-s' in listofnames: 
        result.append((c+"-l",c+'-s')) 
       else: 
        result.append((c+"-l",None)) 
      else: 
       result.append((None,c+"-s")) 
     return result 

Ergebnis wie folgt aussieht:

[(None, 'green-s'), ('red-l', 'red-s'), ('blue-l', 'blue-s')] 
0
listOfNames = ['red-l','blue-l','green-s','red-s','blue-s'] 
l_list = [a[:-2] for a in filter(lambda x:x[-1]=='l',listOfNames)] 
s_list = [a[:-2] for a in filter(lambda x:x[-1]=='s',listOfNames)] 
s = {a[:-2] for a in listOfNames} 
tuplesOfNames = [tuple([c+'-l' if c in l_list else None,c+'-s' if c in s_list else None]) for c in s] 

Ausgang:

[('blue-l', 'blue-s'), ('red-l', 'red-s'), (None, 'green-s')] 

Dies wird schneller sein, leicht als Alternativen aufgrund spliting in zwei separate Listen für Elemente, so dass Lookup schneller Bit.

0

denke ich, eine schöne (und vielleicht besser) Lösung ist:

from collections import defaultdict 
d = defaultdict(list) 
listOfNames = ['red-l','blue-l','green-s','red-s','blue-s'] 
# Go over the list and remember for each color the entry 
for s in listOfNames: 
    d[s[:-2]].append(s[-1]) 
# Go over the colors and produce the appropriate tuple 
[ (key+'-l' if 'l' in d[key] else None, key+'-s' if 's' in d[key] else None) for key in d.keys() ] 

Das gibt:

[('blue-l', 'blue-s'), ('red-l', 'red-s'), (None, 'green-s')] 

Mit dieser Methode können Sie nur einmal über die ursprüngliche Liste gehen und einmal über die Farbtasten (die kleiner ist).

Der Zugriff auf das Wörterbuch ist im Durchschnitt O(1), so dass sollte schnell genug arbeiten.