it-swarm.com.de

Nicht-alphanumerische Listenreihenfolge von os.listdir ()

Ich verwende oft Python, um Verzeichnisse von Daten zu verarbeiten. Ich habe kürzlich festgestellt, dass sich die Standardreihenfolge der Listen in etwas fast unsinniges geändert hat. Wenn ich beispielsweise in einem aktuellen Verzeichnis bin, das die folgenden Unterverzeichnisse enthält: run01, run02, ... run19, run20 und dann generiere ich eine Liste mit dem folgenden Befehl:

dir = os.listdir(os.getcwd())

dann bekomme ich normalerweise eine Liste in dieser Reihenfolge:

dir = ['run01', 'run18', 'run14', 'run13', 'run12', 'run11', 'run08', ... ]

und so weiter. Die Reihenfolge war früher alphanumerisch. Aber diese neue Ordnung ist schon eine Weile bei mir geblieben.

Was bestimmt die (angezeigte) Reihenfolge dieser Listen?

68
marshall.ward

Ich denke, die Reihenfolge hat mit der Art und Weise zu tun, wie die Dateien auf Ihrem Dateisystem indiziert werden. Wenn Sie wirklich eine Reihenfolge festlegen möchten, können Sie die Liste nach dem Abrufen der Dateien sortieren.

44
Nowayz

Sie können die eingebaute Funktion sorted verwenden, um die Zeichenfolgen nach Belieben zu sortieren. Basierend auf dem, was Sie beschreiben, 

sorted(os.listdir(whatever_directory))

Alternativ können Sie die .sort-Methode einer Liste verwenden:

lst = os.listdir(whatever_directory)
lst.sort()

Ich denke, sollte den Trick tun.

Beachten Sie, dass die Reihenfolge der Dateinamen von os.listdir wahrscheinlich vollständig von Ihrem Dateisystem abhängt.

84
mgilson

Per Dokumentation :

os.listdir (Pfad) 

Eine Liste zurückgeben mit den Namen der Einträge in das durch path angegebene Verzeichnis. Die Liste ist in beliebiger Reihenfolge. Es tut nicht Fügen Sie die speziellen Einträge '.' und '..' auch wenn sie in der .__ vorhanden sind. Verzeichnis.

Ordnung ist nicht verlässlich und ein Artefakt des Dateisystems.

Um das Ergebnis zu sortieren, verwenden Sie sorted(os.listdir(path)).

34
Mark Tolonen

Aus irgendeinem Grund gibt es in Python keine eingebaute Möglichkeit, eine natürliche Sortierung zu haben (dh 1, 2, 10 anstelle von 1, 10, 2). Sie müssen es also selbst schreiben:

import re
def sorted_aphanumeric(data):
    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(data, key=alphanum_key)

Mit dieser Funktion können Sie jetzt eine Liste sortieren:

dirlist = sorted_aphanumeric(os.listdir(...))
7
user136036

Es ist wahrscheinlich nur die Reihenfolge, die Cs readdir() zurückgibt. Versuchen Sie, dieses C-Programm auszuführen:

#include <dirent.h>
#include <stdio.h>
int main(void)
{   DIR *dirp;
    struct dirent* de;
    dirp = opendir(".");
    while(de = readdir(dirp)) // Yes, one '='.
        printf("%s\n", de->d_name);
    closedir(dirp);
    return 0;
}

Die Build-Zeile sollte etwa gcc -o foo foo.c sein.

P.S. Ich habe nur diesen und Ihren Python-Code ausgeführt, und beide haben mir eine sortierte Ausgabe gegeben, sodass ich nicht reproduzieren kann, was Sie sehen.

5
Mike DeSimone

Ich denke, standardmäßig wird die Reihenfolge mit dem Wert ASCII bestimmt. Die Lösung für dieses Problem ist dies

dir = sorted(os.listdir(os.getcwd()), key=len)
3
Zied Khlif

Ich fand "sort" tut nicht immer das, was ich erwartet hatte. Ich habe zB ein Verzeichnis wie unten und die "Sortierung" ergibt ein sehr seltsames Ergebnis:

>>> os.listdir(pathon)
['2', '3', '4', '5', '403', '404', '407', '408', '410', '411', '412', '413', '414', '415', '416', '472']
>>> sorted([ f for f in os.listdir(pathon)])
['2', '3', '4', '403', '404', '407', '408', '410', '411', '412', '413', '414', '415', '416', '472', '5']

Es scheint, als würde das erste Zeichen zuerst verglichen werden. Wenn dies das größte Zeichen ist, wäre es das letzte Zeichen.

2
Jue
aaa = ['row_163.pkl', 'row_394.pkl', 'row_679.pkl', 'row_202.pkl', 'row_1449.pkl', 'row_247.pkl', 'row_1353.pkl', 'row_749.pkl', 'row_1293.pkl', 'row_1304.pkl', 'row_78.pkl', 'row_532.pkl', 'row_9.pkl', 'row_1435.pkl']                                                                                                                                                                                                                                                                                                 
sorted(aaa, key=lambda x: int(os.path.splitext(x.split('_')[1])[0]))

Wenn es sich um meine Anforderung handelt, habe ich den Fall wie row_163.pkl hier os.path.splitext('row_163.pkl') wird ihn in ('row_163', '.pkl') aufteilen, also muss er auch basierend auf '_' aufgeteilt werden.

aber im Falle Ihrer Anforderung können Sie etwas tun

sorted(aa, key = lambda x: (int(re.sub('\D','',x)),x))

woher 

aa = ['run01', 'run08', 'run11', 'run12', 'run13', 'run14', 'run18']

und auch zum Abrufen von Verzeichnissen können Sie sorted(os.listdir(path))

und für den Fall von wie 'run01.txt' oder 'run01.csv' können Sie dies tun 

sorted(files, key=lambda x : int(os.path.splitext(x)[0]))
1
rajeshcis
In [6]: os.listdir?

Type:       builtin_function_or_method
String Form:<built-in function listdir>
Docstring:
listdir(path) -> list_of_strings
Return a list containing the names of the entries in the directory.
path: path of directory to list
The list is in **arbitrary order**.  It does not include the special
entries '.' and '..' even if they are present in the directory.
1
Denis

Die vorgeschlagene Kombination von os.listdir und Sorted Befehlen erzeugt dasselbe Ergebnis wie der Befehl ls -l unter Linux. Das folgende Beispiel bestätigt diese Annahme:

[email protected]:/tmp/test$ touch 3a 4a 5a b c d1 d2 d3 k l p0 p1 p3 q 410a 409a 408a 407a
[email protected]:/tmp/test$ ls -l
total 0
-rw-rw-r-- 1 user user 0 Feb  15 10:31 3a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 407a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 408a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 409a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 410a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 4a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 5a
-rw-rw-r-- 1 user user 0 Feb  15 10:31 b
-rw-rw-r-- 1 user user 0 Feb  15 10:31 c
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d1
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d2
-rw-rw-r-- 1 user user 0 Feb  15 10:31 d3
-rw-rw-r-- 1 user user 0 Feb  15 10:31 k
-rw-rw-r-- 1 user user 0 Feb  15 10:31 l
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p0
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p1
-rw-rw-r-- 1 user user 0 Feb  15 10:31 p3
-rw-rw-r-- 1 user user 0 Feb  15 10:31 q

[email protected]:/tmp/test$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.listdir( './' )
['d3', 'k', 'p1', 'b', '410a', '5a', 'l', 'p0', '407a', '409a', '408a', 'd2', '4a', 'p3', '3a', 'q', 'c', 'd1']
>>> sorted( os.listdir( './' ) )
['3a', '407a', '408a', '409a', '410a', '4a', '5a', 'b', 'c', 'd1', 'd2', 'd3', 'k', 'l', 'p0', 'p1', 'p3', 'q']
>>> exit()
[email protected]:/tmp/test$ 

Für jemanden, der das Ergebnis des bekannten Befehlsls -lin seinem Python-Code reproduzieren möchte, istsortiert (os.listdir (DIR)) ziemlich gut.

0
funk

Elliots Antwort löst es perfekt, aber weil es ein Kommentar ist, bleibt es unbemerkt. Mit dem Ziel, jemandem zu helfen, möchte ich es als Lösung wiederholen.

Natsort-Bibliothek verwenden: 

Installieren Sie die Bibliothek mit dem folgenden Befehl für Ubuntu und andere Debian-Versionen 

Python 2

Sudo pip install natsort

Python 3

Sudo pip3 install natsort

Details zur Verwendung dieser Bibliothek finden Sie hier hier

0
rocksyne