2016-09-02 4 views
0

Ich versuche, eine Liste in Python zu sortieren, aber eine, die sowohl Buchstaben als auch Zahlen in demselben Begriff enthält. Das Problem mit der Art mit auf eine Zeichenfolge ist, dass es nicht die Zahlen richtig funktioniert sortieren:Sortieren einer kombinierten Liste von Zahlen und Buchstaben in Python

2 
23 
3 

etc

list = [("a", ['8', '0']), ("a", ['7', '0b']), ("a", ['7', '0']), ("a", ['6', '0b']), ("a", ['6', '01']] 

new_list = sorted(list, key=lambda i: i[1]) 
# works great on ints. 

Die Buchstaben sortiert werden müssen, da es Zahl Äquivalent, das heißt:

a = 1, b = 2, c = 3, d = 4 etc 

daher 4.1a == 4.11

Aber ich brauche t o Bewahre den Buchstaben in der Ausgabe und wandle ihn nicht einfach in einen int um. Irgendwelche Ideen?

+2

Was ist das erwartete Ergebnis für die Eingabe, die Sie gezeigt haben? – thefourtheye

+0

Schreibe eine Funktion, die 'i [1]' in einen String konvertiert, ersetzt 'a' durch' 1', 'b' durch' 2' etc in der Zeichenkette und gibt dann den in float konvertierten String zurück Schlüssel "? – nekomatic

+0

Das obige klingt perfekt. Ich werde versuchen, herauszufinden, wie man das macht (ich bin neu in fortgeschrittenem Python). –

Antwort

0

Hier ist meine Lösung:

def f(s): 
    m = {'a': 1,'b': 2,'c': 3,'d': 4,'e': 5, 
     'f': 6,'g': 7,'h': 8,'i': 9,'j': 10, 
     'k': 11,'l': 12,'m': 13,'n': 14,'o': 15, 
     'p': 16,'q': 17,'r': 18,'s': 19, 
     't': 20,'u': 21,'v': 22,'w': 23, 
     'x': 24,'y': 25,'z': 26} 
    result = [] 
    for l in s: 
     try: 
      result.append(int(l)) 
     except ValueError: 
      result.append(m[l]) 
    return result 

list = [("a", ['8', '0']), ("a", ['7', '0b']), ("a", ['7', '0']), ("a", ['6', '0b']), ("a", ['6', '01'])] 
new_list = sorted(list, key=lambda i: f(''.join(i[1]))) 

>>> new_list 
[('a', ['6', '01']), 
('a', ['6', '0b']), 
('a', ['7', '0']), 
('a', ['7', '0b']), 
('a', ['8', '0'])] 

Die Funktion wandelt so etwas wie ‚60b‘ auf [6,0,2] (die Buchstaben auf ganze Zahlen nach dem Mapping dict Dann Lambda Sorten auf der Grundlage des umgewandelt werden.

+0

Ich vermute, das OP möchte '['7', '0']' vor '[' 6 ',' 01 '] 'in sortierter Reihenfolge erscheinen. –

+0

@ PM2Ring Ich glaube nicht, '['7', '0']' sollte Version 7.0 bedeuten, die nach Version 6.01 geht. Wenn Sie jedoch recht haben, reicht es aus, 'f (''. Join (i [1]))' zu 'f (i [1] [1])' im Lambda-Ausdruck zu ändern. –

0

Es ist nicht ganz klar aus Ihrer Frage, aber ich nehme an, dass Sie das erste Element in jedem Tupel ignorieren, und nur auf der Liste in dem zweiten Element sortiere ich nehme auch an, dass nur Buchstaben von ' a 'bis' i 'kann in dieser Liste vorkommen.

Ein einfacher Weg, um ein -> 1, b -> 2, c -> 3, ... i -> 9 zu konvertieren, ist die Tatsache, dass die ASCII-Codes der Ziffern Zeichen zusammenhängend sind und so sind Kleinbuchstaben. Somit gibt es einen konstanten Offset von 48 zwischen jedem Buchstaben und seiner äquivalenten Ziffer.

Um eine Liste von Strings in einen Schlüssel zu konvertieren, können wir alle Strings zu einer einzigen Zeichenfolge zusammenfügen, dann jedes Buchstabenzeichen in der Zeichenfolge in das entsprechende Zeichen umwandeln, die resultierenden Zeichen zurück in eine einzige Zeichenfolge und wandle diese Zeichenfolge in eine Ganzzahl um.

lst = [ 
    ("a", ['8', '0']), 
    ("a", ['7', '0b']), 
    ("a", ['7', '0']), 
    ("a", ['6', '0b']), 
    ("a", ['6', '01']), 
] 

def keyfunc(t): 
    a = [chr(ord(c) - 48) if 'a' <= c <= 'i' else c for c in ''.join(t[1])] 
    return int(''.join(a)) 

new_lst = sorted(lst, key=keyfunc) 
for row in new_lst: 
    print(row) 

Ausgang

('a', ['7', '0']) 
('a', ['8', '0']) 
('a', ['6', '01']) 
('a', ['6', '0b']) 
('a', ['7', '0b']) 

BTW, sollten Sie nicht list als Variablennamen verwenden, da dies die eingebauten in list Art Schatten, und das zu mysteriösen Fehlern führen kann.

0

Machst du eine inkrementelle Sortierung oder sortierst du nur nach den a1 Elementen?

Wenn Sie wirklich einen Zahlenwert für einen Brief erhalten müssen, können Sie wahrscheinlich verwenden string.ascii_letters.index(letter) Oder noch besser, wenn Sie aufeinander folgende Zahlen für Buchstaben benötigen, ein < = b, Verwendung ord(letter).

Aber ich denke Buchstaben sollten richtig sortieren, ohne einen ganzzahligen Wert zu erhalten. Ich denke, das Problem ist das Teilen ['a', 'a1'].

Ich bin mir nicht sicher, ob dies ist, was Sie brauchen:

def sort_func(item): 
    try: 
     return item[1][1][1] 
    except: 
     return item[1][1] 

# sort by the alphanumeric 
vals.sort(key=sort_func) 
# sort again by the number 
vals.sort(key=lambda i: int(i[1][0])) 
# sort again by the first letter 
vals.sort(key=lambda i:i[0]) 
Verwandte Themen