Os.listdir () এর থেকে অ-অক্ষর সংক্রান্ত তালিকা আদেশ


108

আমি প্রায়শই ডেটার ডিরেক্টরিগুলি প্রক্রিয়া করার জন্য পাইথন ব্যবহার করি। সম্প্রতি, আমি লক্ষ করেছি যে তালিকার ডিফল্ট ক্রমটি প্রায় অযৌক্তিক কিছুতে পরিবর্তিত হয়েছে। উদাহরণস্বরূপ, যদি আমি নিম্নলিখিত সাব-ডাইরেক্টরিগুলি সহ একটি বর্তমান ডিরেক্টরিতে থাকি: রান01, রান02, ... রান 19, রান20, এবং তারপরে আমি নিম্নলিখিত কমান্ড থেকে একটি তালিকা তৈরি করি:

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

তারপরে আমি সাধারণত এই ক্রমে একটি তালিকা পাই:

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

ইত্যাদি। অর্ডারটি আলফানিউমারিক হত। তবে এই নতুন আদেশটি আমার কাছে কিছুক্ষণ রয়ে গেছে।

এই তালিকার (প্রদর্শিত) ক্রমটি কী নির্ধারণ করছে?


পাইথন তালিকার মধ্যে অর্ডার আসলে প্রাসঙ্গিক (যেমন তালিকাগুলি অর্ডার করা হয়)। আমি নোয়ায়েজের সাথে একমত: আপনি যে অদ্ভুত ক্রমটি দেখছেন সেটি সম্ভবত ফাইল সিস্টেমের একটি কাজ। আমি কয়েক বছর আগে ম্যাকের সাথে যুক্ত একটি তৃতীয় পক্ষের নেটওয়ার্ক ফাইল সিস্টেমের সাথে এটি ঘটতে দেখেছি।
ডেভিড পি সাইমনস

তথ্যের জন্য আপনাকে ধন্যবাদ, আমি তালিকা আদেশের মন্তব্যটি মুছে ফেলেছি।
marshall.ward

@ শোগ 9 ঠিক আছে, এখন আমি দেখতে পাচ্ছি যে প্রশ্নটি জিজ্ঞাসা করা হয়েছিল, এবং উত্তর দেওয়া হয়েছিল (লিঙ্কিত উত্তরে ডেটা বাছাইয়ের উপায় কখনই সরবরাহ করা হয়নি) তবে প্রশ্নের বিষয়টি খুব পরিষ্কার ছিল না (এমন কোনও অনুসন্ধান যা উত্তর উপস্থিত হয়নি) এবং ট্যাগগুলি খুব সহায়ক ছিল না
দিমিত্রিস

@ ডিমিট্রিস: এটি একটি ন্যায্য সমালোচনা - আমি এটিকে একটি পুনরায় সরিয়ে নিয়েছি এবং দুটি প্রশ্ন একত্রিত করেছি, সুতরাং এখন উভয় উত্তর এখানে পাওয়া যাবে এবং আপনার দিকে ইঙ্গিত করা থাকবে।
শোগ 9

বিটিডাব্লু যদি অন্য যেহেতু আমি এখানে উত্তরগুলি সম্পর্কে ঠিক তেমনি বিভ্রান্ত হয়ে পড়েছি, কারণ আমার প্রশ্নটি সাজানো 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()আমাকে দিয়েছিল: টাইপ-এয়ারার: ​​'ননটাইপ' অবজেক্টটি পুনরাবৃত্ত নয়
পল_h

1
@ অ্যালেক্সবি - অবশ্যই ... reverse=Trueএটিকে অবতরণ সাজানোর জন্য পাস করুন ।
মিগিলসন

1
@ ব্যবহারকারী 3895596 - আমি মনে করি যে sortedপ্রথমে লিখিত জিনিসটি এটি একটি এক লাইনে ঠিক আছে?
মিগিলসন

43

ডকুমেন্টেশন প্রতি :

os.listdir (পথ)

ডিরেক্টরি অনুসারে ডিরেক্টরিতে প্রবেশের নাম সম্বলিত একটি তালিকা ফেরত দিন। তালিকাটি স্বেচ্ছাসেবী ক্রমে । এটিতে বিশেষ এন্ট্রি অন্তর্ভুক্ত নয়। ' এবং '..' এমনকি তারা ডিরেক্টরিতে উপস্থিত থাকলেও।

অর্ডারের উপর নির্ভর করা যায় না এবং এটি ফাইল সিস্টেমের একটি নিদর্শন।

ফলাফলটি সাজানোর জন্য ব্যবহার করুন sorted(os.listdir(path))


26

পাইথন যে কোনও কারণেই প্রাকৃতিক বাছাইয়ের অন্তর্নির্মিত পদ্ধতিতে আসে না (অর্থাত 1, 2, 10 এর পরিবর্তে 1, 10, 2), তাই আপনাকে এটি নিজে লিখতে হবে:

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(...))

সমস্যাগুলি: আপনি যদি উপরের ফাংশনটি স্ট্রিংগুলি সাজানোর জন্য (উদাহরণস্বরূপ ফোল্ডারের নাম) ব্যবহার করেন এবং উইন্ডোজ এক্সপ্লোরারের মতো সেগুলি সাজানোর জন্য চান তবে এটি কিছু প্রান্তের ক্ষেত্রে সঠিকভাবে কাজ করবে না।
এই বাছাই ফাংশনটি যদি উইন্ডোতে নির্দিষ্ট 'বিশেষ' অক্ষরের সাথে ফোল্ডারের নাম থাকে তবে এটি ভুল ফলাফলগুলি প্রদর্শন করবে। উদাহরণস্বরূপ এই ফাংশনটি বাছাই করবে 1, !1, !a, a, যেখানে উইন্ডোজ এক্সপ্লোরার বাছাই করবে !1, 1, !a, a

সুতরাং আপনি যদি উইন্ডোজ এক্সপ্লোরার পাইথনে ঠিক ঠিক সাজানোর জন্য আপনাকে উইন্ডোজ অন্তর্নির্মিত ফাংশন 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()উপরের ফাংশনটির চেয়ে খানিকটা ধীর ।
natsortedআপনার লাইব্রেরি দেব ভুল যদি আপনি আশা করতে উইন্ডোজ এক্সপ্লোরার বাছাই, তাই ব্যবহার ফলাফলে winsort()যে জন্য।


পুরোপুরি সূক্ষ্ম কাজ করে। print( sorted_aphanumeric(["1", "10", "2", "foo_10", "foo_8"]) )-> ['1', '2', '10', 'foo_8', 'foo_10']। ঠিক যেমনটি প্রত্যাশিত
ব্যবহারকারী 136036

natsortedউইন্ডোজ এক্সপ্লোরার ম্যাচের কার্যকারিতা বাস্তবায়নের জন্য দীর্ঘকালীন উন্মুক্ত সমস্যা রয়েছে । সম্ভবত আপনি একটি সমাধান অবদান করা উচিত? github.com/SethMMorton/natsort/issues/41
শেঠমোর্টন

8

আমি মনে করি ডিফল্টরূপে অর্ডার ASCII মান দিয়ে নির্ধারিত হয়। এই সমস্যার সমাধান এটি

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

5

এটি সম্ভবত কেবল অর্ডার যে সি readdir()ফিরে আসে। এই সি প্রোগ্রামটি চালানোর চেষ্টা করুন:

#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
যে কারণে আপনি সকেটে আউটপুটটি দেখছেন তা অনেকগুলি কারণের উপর নির্ভর করে, যেমন ওএস, ফাইল সিস্টেম, ফাইল তৈরির সময়, শেষ ডিফ্র্যাগমেন্টেশনের সময় ক্রিয়া, ...
জোচিম সৌর

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
এক্সো

2
@ অ্যাক্সো সঠিক, কারণ এই মুহুর্তে আপনি সংখ্যার পরিমাণগত মান নয়, বর্ণমালা অনুসারে তুলনা করছেন। আপনার প্রত্যাশার অনুরূপ সাজানোর জন্য, আপনি আপনার ফোল্ডারে নম্বর প্যাডিং ব্যবহার করতে চাইতে পারেন ... ['002', '003', '004', '005', '403', '404', ' 405 ',' 406 ']
অ্যান্ড্রু

2

ডকুমেন্টেশন থেকে :

তালিকাটি নির্বিচারে রয়েছে এবং বিশেষ এন্ট্রিগুলিকে অন্তর্ভুক্ত করে না '' এবং '..' এমনকি তারা ডিরেক্টরিতে উপস্থিত থাকলেও।

এর অর্থ হ'ল অর্ডারটি সম্ভবত ওএস / ফাইল সিস্টেম নির্ভর, এর কোনও বিশেষ অর্থবোধক ক্রম নেই এবং তাই বিশেষত কোনও কিছু হওয়ার নিশ্চয়তা নেই। যতগুলি উত্তর উল্লিখিত হয়েছে: যদি পছন্দ হয় তবে পুনরুদ্ধার করা তালিকাটি বাছাই করা যায়।

চিয়ার্স :)


2

এলিয়টের উত্তর এটিকে নিখুঁতভাবে সমাধান করে তবে এটি একটি মন্তব্য, কারও সাহায্য করার লক্ষ্যে এটি নজরে আসে না, আমি সমাধান হিসাবে এটি পুনরুক্তি করছি।

নাটসোর্ট লাইব্রেরি ব্যবহার করুন:

উবুন্টু এবং অন্যান্য ডেবিয়ান সংস্করণগুলির জন্য নিম্নলিখিত কমান্ড সহ গ্রন্থাগারটি ইনস্টল করুন

পাইথন 2

sudo pip install natsort

পাইথন ঘ

sudo pip3 install natsort

এই গ্রন্থাগারটি কীভাবে ব্যবহার করবেন সে সম্পর্কে বিস্তারিত এখানে পাওয়া যায়


1
তার চেয়েও বেশি নির্ভুল sorted()! ধন্যবাদ
ফরিদ আলজানী

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
ওপি কেবল কেন, কীভাবে তা জানতে চায়।
ডেনিস

@ ডেনিস এটি দেখানোর জন্য ধন্যবাদ - আমি এটি আগে লক্ষ্য করি নি
দিমিত্রিস

@ ড্যানিয়েল ওয়াটকিনস ঠিক আছে, তা নয়))
ডেনিস

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)) বেশ ভাল কাজ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.