2010-04-19 15 views
46

zu sortieren habe ich einen SatzWie alphanumerischen Satz in Python

set(['booklet', '4 sheets', '48 sheets', '12 sheets']) 

Nach der Sortierung ich es wie

4 sheets, 
12 sheets, 
48 sheets, 
booklet 

Jede Idee, bitte

Antwort

43

Kurz und gut:

sorted(data, key=lambda item: (int(item.partition(' ')[0]) 
           if item[0].isdigit() else float('inf'), item)) 

Diese Version:

  • Arbeiten in Python 2 und Python 3, weil:
    • Es ist nicht davon ausgehen, Sie Strings vergleichen und Ganzzahlen (die in Python 3 nicht funktionieren)
    • Es ist verwenden, um die nicht cmp Parameter sorted
  • Wird auf der Saite Teil sortieren (was nicht in Python 3 nicht vorhanden ist), wenn die Mengen

gleich Wenn Sie gedruckte Ausgabe genau wollen wie in Ihrem Beispiel beschrieben, dann:

data = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) 
r = sorted(data, key=lambda item: (int(item.partition(' ')[0]) 
            if item[0].isdigit() else float('inf'), item)) 
print ',\n'.join(r) 
+1

Große Antwort Daniel – mmrs151

1
>>> a = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) 
>>> def ke(s): 
    i, sp, _ = s.partition(' ') 
    if i.isnumeric(): 
     return int(i) 
    return float('inf') 

>>> sorted(a, key=ke) 
['4 sheets', '12 sheets', '48 sheets', 'booklet'] 
1

Sätze sind von Natur aus aussehen wollen ungeordnet. Sie müssen eine Liste mit demselben Inhalt erstellen und diese sortieren.

+2

Nicht wahr - die sortierte() Built-in wird eine Sequenz nehmen und eine sortierte Liste zurück . – PaulMcG

+3

Anstatt also eine Liste zu erstellen und sie zu sortieren, verwenden Sie stattdessen eine eingebaute, um eine sortierte Liste zu erstellen .... Ja, ich war weg. – Rakis

1

Basierend auf SilentGhost Antwort:

In [4]: a = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) 

In [5]: def f(x): 
    ...:  num = x.split(None, 1)[0] 
    ...:  if num.isdigit(): 
    ...:   return int(num) 
    ...:  return x 
    ...: 

In [6]: sorted(a, key=f) 
Out[6]: ['4 sheets', '12 sheets', '48 sheets', 'booklet'] 
83

Jeff Atwood spricht über natürliche Art und gibt ein Beispiel für eine Möglichkeit, es in Python zu tun. Hier ist meine Variation darauf:

import re 

def sorted_nicely(l): 
    """ Sort the given iterable in the way that humans expect.""" 
    convert = lambda text: int(text) if text.isdigit() else text 
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(l, key = alphanum_key) 

Verwendung wie folgt aus:

s = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) 
for x in sorted_nicely(s): 
    print(x) 

Ausgang:

4 sheets 
12 sheets 
48 sheets 
booklet 

Ein Vorteil dieser Methode ist, dass es nicht nur, wenn funktioniert die Saiten sind durch Leerzeichen getrennt. Es funktioniert auch für andere Trennzeichen wie den Zeitraum in Versionsnummern (zum Beispiel steht 1.9.1 vor 1.10.0).

+0

Hallo Jeff, Vielen Dank. Genau das habe ich gesucht. Viel Glück. – mmrs151

+2

Ist es möglich, dies für eine Liste von Tupeln basierend auf dem ersten Wert im Tupel zu ändern?Beispiel: '[('b', 0), ('0', 1), ('a', 2)]' wird nach '[(' 0 ', 1), (' a ', 2) sortiert, ('b', 0)] ' – paragbaxi

+3

Diese Funktion unterscheidet zwischen Groß- und Kleinschreibung. Großbuchstaben werden Vorrang haben. Um das zu beheben, fügen Sie '.lower()' zu 'key' in' re.split' hinzu. – zamber

6

Eine einfache Möglichkeit besteht darin, die Strings in numerische Teile und nichtnumerische Teile aufzuteilen und die Sortierfolge python tuple zum Sortieren der Strings zu verwenden.

import re 
tokenize = re.compile(r'(\d+)|(\D+)').findall 
def natural_sortkey(string):   
    return tuple(int(num) if num else alpha for num, alpha in tokenize(string)) 

sorted(my_set, key=natural_sortkey) 
3

es wurde vorgeschlagen, dass ich this answer hier umbuchen, da es schön für diesen Fall funktioniert auch

Demo:

>>> my_set = {'booklet', '4 sheets', '48 sheets', '12 sheets'} 
>>> sorted(my_set, key=keyfunc) 
['4 sheets', '12 sheets', '48 sheets', 'booklet'] 

Für Python3 notwendig es ist es leicht zu ändern (diese Version in Python2 auch ok funktioniert)

def keyfunc(s): 
    return [int(''.join(g)) if k else ''.join(g) for k, g in groupby('\0'+s, str.isdigit)] 
1

Für mit einer Pre-2.4-Version von Python stecken Menschen, Ohne die wunderbare sorted() Funktion ist ein schneller Weg, Sätze zu sortieren:

l = list(yourSet) 
l.sort() 

Dies beantwortet nicht die spezifische Frage oben (12 sheets wird vor 4 sheets kommen), aber es könnte für Leute von Google nützlich sein.

4

Sie sollten die dritte Partei Bibliothek natsort überprüfen. Sein Algorithmus ist allgemein, so dass er für die meisten Eingaben funktioniert.

>>> import natsort 
>>> your_list = set(['booklet', '4 sheets', '48 sheets', '12 sheets']) 
>>> print ',\n'.join(natsort.natsorted(your_list)) 
4 sheets, 
12 sheets, 
48 sheets, 
booklet 
0

Generische Antwort, um beliebige Zahlen in einer beliebigen Position in einem Array von Zeichenfolgen zu sortieren. Kompatibel mit Python 2 & 3.

def alphaNumOrder(string): 
    """ Returns all numbers on 5 digits to let sort the string with numeric order. 
    Ex: alphaNumOrder("a6b12.125") ==> "a00006b00012.00125" 
    """ 
    return ''.join([format(int(x), '05d') if x.isdigit() 
        else x for x in re.split(r'(\d+)', string)]) 

Probe:

s = ['a10b20','a10b1','a3','b1b1','a06b03','a6b2','a6b2c10','a6b2c5'] 
s.sort(key=alphaNumOrder) 
s ===> ['a3', 'a6b2', 'a6b2c5', 'a6b2c10', 'a06b03', 'a10b1', 'a10b20', 'b1b1'] 

Ein Teil der Antwort is from there

Verwandte Themen