2015-12-30 14 views
5

ich Daten in einer Textdatei teilen, die "Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002" enthält.Wie ein gemischten String mit Zahlen

Ist es möglich, es ohne das Wort "Test DATA_" zu sortieren, so werden die Daten wie g001, g002, g003 usw. sortiert?

Ich versuchte, die .split("Test DATA_") Methode, aber es funktioniert nicht.

def readFile(): 
    #try block will execute if the text file is found 
    try: 
     fileName = open("test.txt",'r') 
     data = fileName.read().split("\n") 
     data.sort (key=alphaNum_Key) #alternative sort function 
     print(data) 
    #catch block will execute if no text file is found 
    except IOError: 
     print("Error: File do not exist") 
     return 

#Human sorting 
def alphaNum(text): 
    return int(text) if text.isdigit() else text 

#Human sorting 
def alphaNum_Key(text): 
    return [ alphaNum(c) for c in re.split('(\d+)', text) ] 

Antwort

7

Sie können dies mit re tun.

import re 
x="Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002" 
print sorted(x.split(","),key= lambda k:int(re.findall("(?<=_g)\d+$",k)[0])) 

Ausgang: [' Test DATA_g001', ' Test DATA_g002', ' Test DATA_g003', 'Test DATA_g004']

+1

Die Sortierfunktion funktioniert einwandfrei. Allerdings habe ich Probleme beim Sortieren von "g001". Wie sortiere ich die Daten ohne die Zeichenkette "Test DATA_"? –

+0

@Aurora_Titanium (x.replace ('TestData', '') für x in xs – Caridorc

+0

@Aurora_Titanium Ich habe nach dem Schlüssel 'integers' am Ende nach' g_' sortiert – vks

3

Ja, Sie können. Sie können durch die letzten drei Ziffern in jedem Teststring sortieren:

# The string to be sorted by digits 
s = "Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002" 

# Create a list by splitting at commas, sort the last 3 characters of each element in the list as `ints`. 
l = sorted(s.split(','), key = lambda x: int(x[-3:])) 

print l 
# [' Test DATA_g001', ' Test DATA_g002', ' Test DATA_g003', 'Test DATA_g004'] 

Hier finden Sie die Elemente von l trimmen wollen, wenn das für Sie wichtig ist, aber das wird für alle Test s arbeiten, die in 3 Ziffern enden.

Wenn Sie nicht Test DATA_ möchten, können Sie dies tun:

# The string to be sorted by digits 
s = "Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002" 

# Create a list by taking the last 4 characters of sorted strings with key as last 3 characters of each element in the list as `int`s. 
l = sorted((x[-4:] for x in s.split(',')), key = lambda x: int(x[-3:])) 

print l 
# ['g001', 'g002', 'g003', 'g004'] 

Wenn Ihre Daten wohlgeformt ist (das heißt, g gefolgt von 3 Ziffern), wird dies ganz gut funktionieren. Ansonsten einen regulären Ausdruck aus einer der anderen geschrieben Antworten verwenden.


Eine weitere Alternative ist Strings in eine PriorityQueue zu schieben, wie Sie sie lesen:

test.py

from Queue import PriorityQueue 

q = PriorityQueue() 

with open("example.txt") as f: 
    # For each line in the file 
    for line in f: 
    # Create a list from the stripped, split-at-comma string 
    for s in line.strip().split(','): 
     # Push the last four characters of each element in the list into the pq 
     q.put(s[-4:]) 

while not q.empty(): 
    print q.get() 

Der Vorteil einer PQ ist, dass es sie in sortierter Reihenfolge hinzufügen wird , das entlastet die von Ihnen, und es wird in linearer Zeit getan.

example.txt

Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002 

Und die Ausgabe:

13:25 $ python test.py 
g001 
g002 
g003 
g004 
+1

Ich schätze Ihre Verwendung von "re" für so einfache und normal aussehende Daten. Ich denke, dass es die Antwort gibt, und was die OP fehlte, klarer. –

5

Abrufen alle Saiten mit g beginnen und dann die Liste sortieren, mit sorted

>>> s = "Test DATA_g004, Test DATA_g003, Test DATA_g001, Test DATA_g002, " 
>>> sorted(re.findall(r'g\d+$', s)) 
['g001', 'g002', 'g003', 'g004'] 

andere Art und Weise, ist zu verwenden Sie nur den integrierten Methoden:

>>> l = [x.split('_')[1] for x in s.split(', ') if x] 
>>> l 
['g004', 'g003', 'g001', 'g002'] 
>>> l.sort() 
>>> l 
['g001', 'g002', 'g003', 'g004'] 
+3

Sehr schöne Lösung. Elegant und sauber. – erip

2

Klingt wie Sie wollen "natürliche Sortierung". Die folgende, kopiert von https://stackoverflow.com/a/4836734/3019689, könnte es tun.

import re 

def natural_sort(l): 
    convert = lambda text: int(text) if text.isdigit() else text.lower() 
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(l, key = alphanum_key) 

aber Sie sagen immer, Sie „ohne die Test DATA_“ sortieren wollen, die mir schon sagt man nicht die ganze Geschichte erzählen. Wenn es buchstäblich Test DATA_jede Zeit wäre, würde es die Sortierung nicht beeinflussen: Sortieren mit oder ohne es; es wäre egal.Ich wette, Sie sind wirklich besorgt über die Tatsache, dass dieses String-Präfix tatsächlich von Dateiname zu Dateiname variiert, und Sie wollen es vollständig ignorieren, was auch immer es ist und nur auf den numerischen Teil konzentrieren. Wenn dies der Fall ist, können Sie else None für else text.lower() in der obigen Liste ersetzen.

Verwandte Themen