Os.listdir से गैर-अल्फ़ान्यूमेरिक सूची क्रम ()


108

मैं अक्सर डेटा की निर्देशिकाओं को संसाधित करने के लिए अजगर का उपयोग करता हूं। हाल ही में, मैंने देखा है कि सूचियों का डिफ़ॉल्ट क्रम बदलकर लगभग निरर्थक हो गया है। उदाहरण के लिए, यदि मैं एक वर्तमान निर्देशिका में हूं जिसमें निम्नलिखित उपनिर्देशिकाएँ हैं: run01, run02, ... run19, run20, और फिर मैं निम्नलिखित कमांड से एक सूची तैयार करता हूं:

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

तब मुझे आमतौर पर इस क्रम में एक सूची मिलती है:

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

और इसी तरह। आदेश अल्फ़ान्यूमेरिक हुआ करता था। लेकिन यह नया आदेश अब थोड़ी देर के लिए मेरे पास रह गया है।

इन सूचियों का निर्धारण (प्रदर्शित) क्रम क्या है?


अजगर सूची के भीतर आदेश वास्तव में प्रासंगिक है (यानी सूचियों का आदेश दिया गया है)। मैं Nowayz से सहमत हूं: आप जो अजीब आदेश देख रहे हैं वह संभवतः फ़ाइल सिस्टम का एक फ़ंक्शन है। मैंने देखा कि यह कुछ साल पहले एक मैक से जुड़ी 3 जी नेटवर्क फाइल सिस्टम के साथ हुआ था।
डेविड पी सिमंस

जानकारी के लिए धन्यवाद, मैंने सूची आदेश टिप्पणी को हटा दिया है।
marshall.ward

@ शोग 9 ठीक है, अब मैं देख सकता हूं कि प्रश्न पूछा गया था, और जिस तरह का उत्तर दिया गया था (लिंक किए गए उत्तर में डेटा को छांटने का तरीका कभी भी उपलब्ध नहीं कराया गया था) लेकिन प्रश्न का विषय बहुत स्पष्ट नहीं था (एक खोज जो उत्तर नहीं दिखाई दे रही थी) और टैग बहुत मददगार नहीं थे
दिमित्रीस 15

@Dimitris: यह एक निष्पक्ष आलोचना है - मैंने इसे एक बार रिट्वीट किया है और दो प्रश्नों को मिला दिया है, इसलिए अब उत्तर के दोनों सेट यहां मिल सकते हैं और आपकी ओर इशारा किया गया है।
शोग

BTW अगर किसी और के रूप में मैं यहाँ के जवाब के बारे में उलझन में हूँ, यह है क्योंकि मेरा सवाल एक और सवाल के साथ विलय कर दिया गया था हल listdirउत्पादन का अनुरोध । मुझे यकीन नहीं है कि सवालों का विलय क्यों किया गया था।
marshall.ward

जवाबों:


63

मुझे लगता है कि आपके फाइलसिस्टम पर फाइलों को अनुक्रमित करने के तरीके के साथ आदेश को करना होगा। यदि आप वास्तव में इसे कुछ आदेश का पालन करना चाहते हैं तो आप फ़ाइलों को प्राप्त करने के बाद हमेशा सूची को सॉर्ट कर सकते हैं।


128

sortedहालाँकि, आप इच्छित स्ट्रिंग्स को सॉर्ट करने के लिए बिल्टिन फ़ंक्शन का उपयोग कर सकते हैं। आपके द्वारा वर्णित के आधार पर,

sorted(os.listdir(whatever_directory))

वैकल्पिक रूप से, आप .sortकिसी सूची की विधि का उपयोग कर सकते हैं :

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

मुझे लगता है कि चाल चलनी चाहिए।

ध्यान दें कि os.listdirफ़ाइल नाम प्राप्त करने का क्रम संभवतः पूरी तरह से आपके फाइल सिस्टम पर निर्भर है।


1
संख्या-प्रथम फ़ाइल नाम (यानी 59.9780radps-0096 9.9746radps-0082 से पहले अभी भी है) से निपटने के क्रम में परिवर्तन नहीं होता है। मुझे लगता है कि यह सब कुछ एक स्ट्रिंग है, इसलिए दशमलव को ठीक से व्यवहार नहीं किया जाता है।
इलियट

2
या नटसॉर्ट लाइब्रेरी का उपयोग करें, जो मैंने अभी पाया।
इलियट

5
केवल sorted(listdir)मेरे लिए काम किया। listdir.sort()मुझे दिया: TypeError: 'noneType' ऑब्जेक्ट iterable नहीं है
paul_h

1
@AlexB - यकीन है ... बस reverse=Trueइसे अवरोही क्रम बनाने के लिए पास करें।
mgilson

1
@ user3895596 - मुझे लगता है कि जो sortedचीज़ सबसे पहले लिखी गई है, वह एक ही पंक्ति में ठीक है?
mgilson

43

प्रति प्रलेखन :

os.listdir (पथ)

पथ द्वारा दी गई निर्देशिका में प्रविष्टियों के नाम वाली सूची लौटाएं। सूची मनमाने क्रम में है । इसमें विशेष प्रविष्टियाँ शामिल नहीं हैं '।' और '..' भले ही वे डायरेक्टरी में मौजूद हों।

आदेश पर भरोसा नहीं किया जा सकता है और फाइलसिस्टम की एक कलाकृति है।

परिणाम को सॉर्ट करने के लिए, उपयोग करें sorted(os.listdir(path))


26

जो भी कारण प्राकृतिक तरीके से छंटाई करने का नहीं है (1, 2, 10 के बजाय 1, 2, 10) के साथ आने वाले पायथन , इसलिए आपको इसे स्वयं लिखना होगा:

import re
def sorted_alphanumeric(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)

अब आप इस फ़ंक्शन का उपयोग सूची को सॉर्ट करने के लिए कर सकते हैं:

dirlist = sorted_alphanumeric(os.listdir(...))

समस्याएँ: यदि आप उपरोक्त फ़ंक्शन का उपयोग स्ट्रिंग्स को सॉर्ट करने के लिए करते हैं (उदाहरण के लिए फ़ोल्डर के नाम) और चाहते हैं कि उन्हें Windows Explorer की तरह सॉर्ट किया जाए, तो यह कुछ एज मामलों में ठीक से काम नहीं करेगा।
यह सॉर्टिंग फ़ंक्शन विंडोज पर गलत परिणाम लौटाएगा, यदि आपके पास कुछ विशिष्ट 'वर्ण' वाले फ़ोल्डर नाम हैं। उदाहरण के लिए यह फ़ंक्शन सॉर्ट करेगा 1, !1, !a, a, जबकि विंडोज एक्सप्लोरर सॉर्ट करेगा !1, 1, !a, a

इसलिए यदि आप ठीक उसी तरह से छांटना चाहते हैं जैसे कि पाइथन में विंडोज एक्सप्लोरर करता है तो आपको ctypes के माध्यम से विंडोज बिल्ट-इन फ़ंक्शन StrCmpLogicalW का उपयोग करना होगा (यह निश्चित रूप से यूनिक्स पर काम नहीं करेगा):

from ctypes import wintypes, windll
from functools import cmp_to_key
def winsort(data):
    _StrCmpLogicalW = windll.Shlwapi.StrCmpLogicalW
    _StrCmpLogicalW.argtypes = [wintypes.LPWSTR, wintypes.LPWSTR]
    _StrCmpLogicalW.restype  = wintypes.INT

    cmp_fnc = lambda psz1, psz2: _StrCmpLogicalW(psz1, psz2)
    return sorted(data, key=cmp_to_key(cmp_fnc))

यह फ़ंक्शन की तुलना में थोड़ा धीमा है sorted_alphanumeric()

बोनस: विंडोज पर पूर्ण पथwinsort भी सॉर्ट कर सकते हैं ।

वैकल्पिक रूप से, विशेष रूप से यदि आप यूनिक्स का उपयोग करते हैं, तो आप natsortलाइब्रेरी ( pip install natsort) को सही तरीके से पूर्ण पथों द्वारा क्रमबद्ध करने का उपयोग कर सकते हैं (जिसका अर्थ है सही स्थिति में सबफ़ोल्डर)।

पूर्ण पथ को सॉर्ट करने के लिए आप इसका उपयोग कर सकते हैं:

from natsort import natsorted, ns
dirlist = natsorted(dirlist, alg=ns.PATH | ns.IGNORECASE)

इसे केवल फ़ोल्डर नामों (या सामान्य रूप से तार) के सामान्य सॉर्टिंग के लिए उपयोग न करें, क्योंकि यह sorted_alphanumeric()ऊपर दिए गए फ़ंक्शन की तुलना में थोड़ा धीमा है । यदि आप Windows Explorer छँटाई की अपेक्षा करते हैं तो
natsortedलाइब्रेरी आपको गलत परिणाम देगा , इसलिए इसके लिए उपयोग करें winsort()


पूरी तरह से ठीक काम करता है। print( sorted_aphanumeric(["1", "10", "2", "foo_10", "foo_8"]) )-> ['1', '2', '10', 'foo_8', 'foo_10']। उम्मीद के मुताबिक।
user136036

natsortedविंडोज एक्सप्लोरर मिलान कार्यक्षमता को लागू करने के लिए एक लंबे समय से खुला मुद्दा है। शायद आपको समाधान में योगदान करना चाहिए? github.com/SethMMorton/natsort/issues/41
सेठमोर्टन

8

मुझे लगता है कि डिफ़ॉल्ट रूप से ऑर्डर ASCII मूल्य के साथ निर्धारित किया जाता है। इस समस्या का हल यह है

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

5

यह शायद सिर्फ आदेश है कि सी का readdir()रिटर्न। इस C प्रोग्राम को चलाने का प्रयास करें:

#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;
}

बिल्ड लाइन कुछ इस तरह होनी चाहिए gcc -o foo foo.c

पीएस बस इसे और आपके पायथन कोड को चलाया, और उन्होंने दोनों को मुझे हल किया आउटपुट, इसलिए मैं पुन: पेश नहीं कर सकता कि आप क्या देख रहे हैं।


1
इसका कारण यह है कि आप बोए गए आउटपुट को बहुत सारे कारकों पर निर्भर कर सकते हैं, जैसे कि OS, फाइलसिस्टम, फाइलों के निर्माण का समय, अंतिम डीफ़्रैग्मेन्टेशन के दौरान की जाने वाली क्रियाएं, ...
जोकिम सॉयर

3
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]))

मेरा आवश्यकता के मामले में जैसा कि मैंने की तरह मामला है row_163.pklयहाँ os.path.splitext('row_163.pkl')में यह टूट जाएगा ('row_163', '.pkl')तो '_' पर भी आधारित यह विभाजित करने के लिए की जरूरत है।

लेकिन अपनी आवश्यकता के मामले में आप ऐसा कुछ कर सकते हैं

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

कहाँ पे

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

और निर्देशिका के लिए भी आप कर सकते हैं sorted(os.listdir(path))

और इस तरह के मामले के लिए 'run01.txt'या 'run01.csv'आप ऐसा कर सकते हैं

sorted(files, key=lambda x : int(os.path.splitext(x)[0]))

2

मैंने पाया "सॉर्ट" हमेशा वह नहीं करता है जिसकी मुझे उम्मीद थी। उदाहरण के लिए, मेरे पास नीचे के रूप में एक निर्देशिका है, और "सॉर्ट" मुझे एक बहुत ही अजीब परिणाम देता है:

>>> 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']

ऐसा लगता है कि यह पहले चरित्र की तुलना पहले करता है, अगर वह सबसे बड़ा है, तो यह आखिरी होगा।


2
यह अपेक्षित व्यवहार है। ('5' > '403') is True
AXO

2
@AXO सही है, क्योंकि इस बिंदु पर आप अल्फ़ान्यूमेरिक प्रकार की तुलना कर रहे हैं, संख्याओं के मात्रात्मक मान नहीं। अपनी अपेक्षा के अनुरूप एक प्रकार पाने के लिए, आप अपने फ़ोल्डरों पर नंबर पैडिंग का उपयोग करना चाह सकते हैं ... ['002', '003', '004', '005', '403', '404', ' 405 ',' 406 ']
एंड्रयू

2

से प्रलेखन :

सूची मनमाने क्रम में है , और इसमें विशेष प्रविष्टियाँ शामिल नहीं हैं '।' और '..' भले ही वे डायरेक्टरी में मौजूद हों।

इसका मतलब यह है कि आदेश शायद ओएस / फाइलसिस्टम निर्भर है, इसका कोई विशेष रूप से सार्थक आदेश नहीं है, और इसलिए विशेष रूप से कुछ भी होने की गारंटी नहीं है। उल्लिखित कई उत्तरों के अनुसार: यदि पसंद किया जाता है, तो पुनः प्राप्त सूची को क्रमबद्ध किया जा सकता है।

चियर्स :)


2

इलियट का जवाब इसे पूरी तरह से हल करता है लेकिन क्योंकि यह एक टिप्पणी है, यह किसी की मदद करने के उद्देश्य से किसी का ध्यान नहीं जाता है, मैं इसे एक समाधान के रूप में दोहरा रहा हूं।

Natsort लाइब्रेरी का उपयोग करें:

उबंटू और अन्य डेबियन संस्करणों के लिए निम्नलिखित कमांड के साथ लाइब्रेरी स्थापित करें

अजगर २

sudo pip install natsort

अजगर ३

sudo pip3 install natsort

इस पुस्तकालय का उपयोग कैसे करें, इसका विवरण यहां पाया गया है


1
की तुलना में अधिक सटीक है sorted()! धन्यवाद
फरीद Alijani

1
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
ओपी सिर्फ यह जानना चाहता है कि क्यों, कैसे नहीं।
डेनिस

@ डेनिस ने इसे इंगित करने के लिए धन्यवाद - मैंने इसे पहले नहीं नोटिस किया
दिमित्री

@DanielWatkins ठीक है, यह नहीं है।)
डेनिस

0

Os.listdir और सॉर्ट किए गए आदेशों का प्रस्तावित संयोजन लिनक्स के तहत ls -l कमांड के समान परिणाम उत्पन्न करता है । निम्नलिखित उदाहरण इस धारणा की पुष्टि करता है:

user@user-PC:/tmp/test$ touch 3a 4a 5a b c d1 d2 d3 k l p0 p1 p3 q 410a 409a 408a 407a
user@user-PC:/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

user@user-PC:/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()
user@user-PC:/tmp/test$ 

तो, कोई है जो अपने पायथन कोड में प्रसिद्ध ls -l कमांड के परिणाम को पुन: उत्पन्न करना चाहता है , सॉर्ट किया गया (os.listdir (DIR)) बहुत अच्छा काम करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.