दो क्षेत्रों द्वारा पायथन सूची को क्रमबद्ध करना


172

मेरे पास एक क्रमबद्ध सीएसवी से बनाई गई निम्नलिखित सूची है

list1 = sorted(csv1, key=operator.itemgetter(1))

मैं वास्तव में सूची को दो मानदंडों के आधार पर क्रमबद्ध करना चाहूंगा: पहले क्षेत्र 1 में मूल्य द्वारा और फिर क्षेत्र 2 में मूल्य के आधार पर। मैं यह कैसे करूं?



क्या हम इस प्रश्न को खड़ा करते हैं और इसके दायरे को "सूची-ऑफ-लिस्ट-ऑफ-लेंथ-टू-बिलिन-टाइप्स (जैसे स्ट्रिंग / इंट / फ्लोट)" तक सीमित करते हैं । या क्या हम "सूची-की-उपयोगकर्ता-परिभाषित-वस्तु" की भी अनुमति देते हैं, जैसा कि शीर्षक से पता चलता है कि अनुमति दी जाती है, इस स्थिति में इसका उत्तर " __lt__()अपनी कक्षा में परिभाषित करने की विधि या कुछ वर्ग से विरासत में मिला" है ? इससे यह कहीं बेहतर विहित होगा।
एसएमसीआई

जवाबों:


157

इस तरह:

import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))

1
+1: मेरी तुलना में अधिक सुंदर। मैं भूल गया कि आइटमगार्ड कई सूचकांक ले सकता है।
dappawit

7
operatorएक मॉड्यूल है जिसे आयात करने की आवश्यकता है।
ट्रेपिकि

3
अगर मैं एक तत्व पर आरोही और दूसरे पर उतरना चाहता हूं, तो आइटमगेटर का उपयोग करके कैसे आगे बढ़ूंगा?
आशीष

3
@ashish, लैम्ब्डा कार्यों के साथ नीचे मेरा उत्तर देखते हैं कि यह स्पष्ट है, तरह से "-x [1]" या "एक्स [0] + x [1]" यदि आप चाहें तो
जाप

क्या होगा अगर उलट मोड में एक मानदंड?
यशकेएच

328

लैम्ब्डा कार्यों का उपयोग करते समय कुछ भी आयात करने की आवश्यकता नहीं है। पहले तत्व द्वारा
निम्नलिखित प्रकार list, फिर दूसरे तत्व द्वारा।

sorted(list, key=lambda x: (x[0], -x[1]))

12
अच्छा लगा। जैसा कि आपने ऊपर मुख्य उत्तर के लिए टिप्पणी में उल्लेख किया है, यह विभिन्न प्रकार के आदेशों के साथ कई प्रकार करने का सबसे अच्छा (केवल?) तरीका है। शायद उस पर प्रकाश डालिए। साथ ही, आपका पाठ यह नहीं दर्शाता है कि आपने दूसरे तत्व पर उतरना छांटा है।
पीटरवर्मट

2
@ user1700890 मैं मान रहा था कि क्षेत्र पहले से ही कठोर था। यह डिफ़ॉल्ट रूप से वर्णानुक्रम में तार को क्रमबद्ध करना चाहिए। आपको अपना प्रश्न एसओ पर अलग से पोस्ट करना चाहिए यदि यह विशेष रूप से यहां के उत्तर या ओपी के मूल प्रश्न से संबंधित नहीं है।
16

5
स्टैंड -में क्या है -x[1]?
Jan

7
@jan यह क्रम उल्टा करें है
जाप

3
एक विशिष्ट मामले में काम नहीं करेगा। स्वीकृत समाधान भी काम नहीं करेगा। उदाहरण के लिए, कुंजी के रूप में उपयोग किए जाने वाले स्तंभ सभी स्ट्रिंग हैं जिन्हें संख्याओं में परिवर्तित नहीं किया जा सकता है। दूसरे, एक कॉलम के आरोही क्रम में और दूसरे कॉलम द्वारा अवरोही क्रम को क्रमबद्ध करना चाहता है।
coder.in.me

20

पाइथन में एक स्थिर सॉर्ट है, इसलिए बशर्ते कि प्रदर्शन कोई समस्या नहीं है सबसे सरल तरीका यह है कि इसे फ़ील्ड 2 से सॉर्ट करें और फिर इसे फ़ील्ड 1 द्वारा फिर से सॉर्ट करें।

इससे आपको जो परिणाम चाहिए वह मिल जाएगा, केवल एक ही पकड़ है कि अगर यह एक बड़ी सूची है (या आप इसे अक्सर छांटना चाहते हैं) तो दो बार कॉल करना एक अस्वीकार्य ओवरहेड हो सकता है।

list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))

इस तरह से करने से उस स्थिति को संभालना भी आसान हो जाता है, जहाँ आप कुछ स्तंभों को उल्टा क्रमबद्ध करना चाहते हैं, बस आवश्यक होने पर 'रिवर्स = ट्रू' पैरामीटर को शामिल करें।

अन्यथा आप आइटमगेटर के लिए कई मापदंडों को पारित कर सकते हैं या मैन्युअल रूप से एक टपल का निर्माण कर सकते हैं। यह संभवतः तेज़ होने वाला है, लेकिन समस्या यह है कि यह अच्छी तरह से सामान्य नहीं होता है यदि कुछ कॉलम रिवर्स सॉर्ट किया जाना चाहते हैं (संख्यात्मक कॉलम अभी भी उन्हें नकारात्मक रूप से उलटा कर सकते हैं लेकिन यह सॉर्ट स्थिर हो रहा है)।

इसलिए यदि आपको किसी कॉलम को उलटने की आवश्यकता नहीं है, तो आइटम के लिए कई तर्कों पर जाएं, यदि आप हो सकते हैं, और कॉलम संख्यात्मक नहीं हैं या आप लगातार कई प्रकारों के लिए सॉर्ट को स्थिर रखना चाहते हैं।

संपादित करें: उन टिप्पणीकारों के लिए जिन्हें यह समझने में समस्या है कि यह मूल प्रश्न का उत्तर कैसे देता है, यहां एक उदाहरण दिया गया है जो बताता है कि छंटनी की स्थिर प्रकृति यह सुनिश्चित करती है कि हम प्रत्येक कुंजी पर अलग-अलग प्रकार कर सकते हैं और कई मानदंडों पर छंटे हुए डेटा के साथ समाप्त हो सकते हैं:

DATA = [
    ('Jones', 'Jane', 58),
    ('Smith', 'Anne', 30),
    ('Jones', 'Fred', 30),
    ('Smith', 'John', 60),
    ('Smith', 'Fred', 30),
    ('Jones', 'Anne', 30),
    ('Smith', 'Jane', 58),
    ('Smith', 'Twin2', 3),
    ('Jones', 'John', 60),
    ('Smith', 'Twin1', 3),
    ('Jones', 'Twin1', 3),
    ('Jones', 'Twin2', 3)
]

# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])

for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

यह एक रन करने योग्य उदाहरण है, लेकिन इसे चलाने वाले लोगों को बचाने के लिए आउटपुट है:

Initial data in random order
Jones      Jane       58
Smith      Anne       30
Jones      Fred       30
Smith      John       60
Smith      Fred       30
Jones      Anne       30
Smith      Jane       58
Smith      Twin2      3
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Jones      Twin2      3

First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Jones      Jane       58
Smith      Jane       58
Smith      John       60
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith      John       60
Jones      John       60
Jones      Jane       58
Smith      Jane       58
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.

Jones      John       60
Jones      Jane       58
Jones      Anne       30
Jones      Fred       30
Jones      Twin1      3
Jones      Twin2      3
Smith      John       60
Smith      Jane       58
Smith      Anne       30
Smith      Fred       30
Smith      Twin1      3
Smith      Twin2      3

विशेष रूप से ध्यान दें कि कैसे दूसरे चरण में reverse=Trueपैरामीटर फर्स्टनाम को क्रम में रखता है जबकि केवल क्रमबद्ध करने के बाद सूची को उलटने से तीसरे क्रम की कुंजी के लिए वांछित ऑर्डर खो जाएगा।


1
स्थिर छँटाई का मतलब यह नहीं है कि यह नहीं भूलेगा कि आपकी पिछली छँटाई क्या थी। यह उत्तर गलत है।
बजे माइक एसेक

7
स्थिर छँटाई का अर्थ है कि आप स्तंभों द्वारा छांट सकते हैं a, b, c केवल स्तंभ c द्वारा छँटाई करके b फिर b फिर a। जब तक आप अपनी टिप्पणी पर विस्तार करने की परवाह नहीं करते, मुझे लगता है कि यह आप है जो गलत है।
डंकन

7
यह उत्तर निश्चित रूप से सही है, हालांकि बड़ी सूचियों के लिए यह एकतरफा है: यदि सूची पहले से ही आंशिक रूप से सॉर्ट की गई थी, तो आप सूची को बहुत अधिक फेरबदल करके अजगर के छंटाई के अधिकांश अनुकूलन को खो देंगे। @ माइक, तुम गलत हो; मैं उन्हें गलत घोषित करने से पहले वास्तव में उत्तर का परीक्षण करने का सुझाव देता हूं।
ग्लेन मेनार्ड

6
@MikeAxiak: docs.python.org/2/library/stdtypes.html#index-29 टिप्पणी 9 में कहा गया है: पायथन 2.3 के साथ, सॉर्ट () विधि स्थिर होने की गारंटी है। एक प्रकार स्थिर होता है यदि यह बराबर की तुलना करने वाले तत्वों के सापेक्ष क्रम को नहीं बदलने की गारंटी देता है - यह कई पास में छंटाई के लिए सहायक है (उदाहरण के लिए, विभाग द्वारा क्रमबद्ध, फिर वेतन ग्रेड द्वारा)।
ट्रेपिकि

यह सही नहीं है क्योंकि यह उनके द्वारा पूछे गए प्रश्न का उत्तर नहीं देता है। वह पहले सूचकांक द्वारा क्रमबद्ध सूची चाहता है और जहां मामले में पहले सूचकांक में संबंध हैं, वह दूसरे सूचकांक का उपयोग छँटाई मानदंडों के रूप में करना चाहता है। एक स्थिर सॉर्ट केवल यह गारंटी देता है कि सभी चीजें समान हैं, जो मूल आदेश पारित किया जाएगा वह आइटम प्रदर्शित होने का क्रम होगा।
जॉन

14
list1 = sorted(csv1, key=lambda x: (x[1], x[2]) )

4
मुझे नहीं लगता कि tuple()दो तर्क प्राप्त कर सकते हैं (या बल्कि, तीन, अगर आप के साथ गिनती self)
Filipe Correia

3
tuple केवल एक तर्क ले सकता है
therealprashant

1
returnबयान होना चाहिए return tuple((x[1], x[2]))या बस return x[1], x[2]। यदि आप अलग-अलग दिशाओं में छँटाई कर रहे हैं तो @jaap उत्तर को नीचे देखें
Jo Kachikaran

… या tuple(x[1:3]), यदि आप किसी कारणवश टपल डिस्प्ले लिस्ट के बजाय टपल कंस्ट्रक्टर का उपयोग करना चाहते हैं x[1], x[2]। या keyfunc = operator.itemgetter(1, 2)खुद भी कोई फंक्शन न लिखें।
17

3
employees.sort(key = lambda x:x[1])
employees.sort(key = lambda x:x[0])

हम 2 बार लैम्ब्डा के साथ .ort का भी उपयोग कर सकते हैं क्योंकि अजगर की तरह जगह और स्थिर है। यह पहले दूसरे तत्व के अनुसार सूची को सॉर्ट करेगा, x [1]। फिर, यह पहला तत्व छाँटेगा, x [0] (सर्वोच्च प्राथमिकता)।

employees[0] = Employee's Name
employees[1] = Employee's Salary

यह निम्न कार्य करने के बराबर है: कर्मचारी.सोर्ट (कुंजी = लैम्ब्डा x: (x [0], x [1]))


1
नहीं, इस छँटाई के नियम को पहले वरीयता लेनी होगी और फिर दूसरी।
कोडरमेर

1

आरोही क्रम में आप उपयोग कर सकते हैं:

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]))

या अवरोही क्रम में आप उपयोग कर सकते हैं:

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]),reverse=True)

0

नीचे का उपयोग करके dicts की सॉर्टिंग सूची पहले कॉलम पर वेतन और दूसरे कॉलम में आयु के रूप में अवरोही क्रम में सूचीबद्ध होगी

d=[{'salary':123,'age':23},{'salary':123,'age':25}]
d=sorted(d, key=lambda i: (i['salary'], i['age']),reverse=True)

आउटपुट: [{: वेतन ’: १२३, [उम्र’: 25}, {: वेतन ’: 123, 'उम्र’: 23}]

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