দুটি ক্ষেত্র দ্বারা পাইথন তালিকা বাছাই করা হচ্ছে


172

আমি একটি তালিকাভুক্ত সিএসভি থেকে নিম্নলিখিত তালিকা তৈরি করেছি

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

আমি তালিকাটি দুটি মানদণ্ড অনুসারে বাছাই করতে চাই: প্রথম ক্ষেত্রের মান দ্বারা এবং তারপরে ক্ষেত্রের মান 2 দিয়ে I আমি কীভাবে এটি করব?



আমরা কি এই প্রশ্নটিকে দাঁড়াতে দিচ্ছি এবং এর ব্যাপ্তিটি কেবল "দুটি-বিল্টিন-টাইম-দৈর্ঘ্যের তালিকাগুলির মধ্যে সীমাবদ্ধ করব (যেমন স্ট্রিং / ইনট / ফ্লোট)" । বা আমরা কি "ব্যবহারকারীর সংজ্ঞায়িত-অবজেক্টের তালিকাকে" অনুমতি দিই , যেমন শিরোনামটিও অনুমোদিত, যেমন ক্ষেত্রে উত্তরটি " __lt__()আপনার শ্রেণিতে পদ্ধতি নির্ধারণ করে বা কোন শ্রেণীর উত্তরাধিকারী" হয় ? এটি এটিকে আরও উন্নততর আধ্যাত্মিক করে তুলবে।
স্মিচ

উত্তর:


157

এটার মত:

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

1
+1: আমার চেয়ে মার্জিত। আমি ভুলে গিয়েছিলাম যে আইটেমজিটার একাধিক সূচক নিতে পারে।
দাপাওয়েট

7
operatorআমদানি করা দরকার এমন একটি মডিউল।
ট্র্যাপিকি

3
আমি যদি আইটেমটেটার ব্যবহার করে কোনও উপাদানটিতে আরোহণ এবং অন্যটিতে নেমে বাছাই করতে চাই তবে কীভাবে এগিয়ে যাব ??
আশীষ

3
@ আশিষ, নীচে ল্যাম্বডা ফাংশন সহ আমার উত্তরটি দেখুন এটি পরিষ্কার, "-x [1]" বা এমনকি "x [0] + x [1]" অনুসারে
বাছাই করুন

বিপরীত মোডে যদি একটি মানদণ্ড হয় তবে কী হবে?
ইয়াসের কে এইচ

328

ল্যাম্বদা ফাংশন ব্যবহার করার সময় কোনও কিছু আমদানি করার দরকার নেই।
নিম্নলিখিত listউপাদানগুলি প্রথম উপাদান অনুসারে, তারপরে দ্বিতীয় উপাদান দ্বারা সাজানো।

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

12
খুশী হলাম। আপনি উপরের মূল উত্তরের মন্তব্যে যেমন উল্লেখ করেছেন যে, বিভিন্ন ধরণের অর্ডার সহ একাধিক ধরণের করার এটি সর্বোত্তম (একমাত্র?) উপায়। সম্ভবত এটি হাইলাইট করুন। এছাড়াও, আপনার পাঠ্যটি ইঙ্গিত দেয় না যে আপনি দ্বিতীয় উপাদানটিতে নেমে বাছাই করেছেন।
পিটারওয়ার্মন্ট

2
@ ব্যবহারকারী 1700890 আমি ধরে নিচ্ছি ফিল্ডটি ইতিমধ্যে স্ট্রিং ছিল। এটি ডিফল্ট অনুসারে স্ট্রিংগুলিকে বর্ণানুক্রমিক ক্রমে বাছাই করা উচিত। আপনার নিজের প্রশ্নটি আলাদা করে এসও-তে পোস্ট করা উচিত যদি এটি নির্দিষ্টভাবে উত্তরটির সাথে সম্পর্কিত না হয় বা ওপি-র মূল প্রশ্নের সাথে।
পিবিবল

5
কি -মধ্যে -x[1]জন্য স্ট্যান্ড?
জানু

7
@ জান এটি বিপরীত সাজান
jaap

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
স্থিতিশীল বাছাই করার অর্থ আপনি ক, ক, খ, সি কলাম দ্বারা সারণি করতে পারবেন কলাম খ এর পরে খ এর পরে খ। আপনি আপনার মন্তব্যে প্রসারিত না করা অবধি আমার মনে হয় ভুল আপনিই এটি।
ডানকান

7
এই উত্তরটি অবশ্যই সঠিক, যদিও বৃহত তালিকার জন্য এটি আনমনীয়: যদি তালিকাটি ইতিমধ্যে আংশিকভাবে বাছাই করা হয়, তবে আপনি পাইথনের বাছাইয়ের বেশিরভাগ অপ্টিমাইজেশন হারাবেন তালিকার আরও অনেকগুলি পরিবর্তন করে। @ মাইক, আপনি ভুল; আমি উত্তরগুলি ভুল ঘোষণার আগে প্রকৃতপক্ষে পরীক্ষার পরামর্শ দিই।
গ্লেন মেইনার্ড 21 '

6
@ মাইকঅ্যাক্সিয়াক: ডকস.পাইথন.আর. / ২ / লিবারি / স্টাডিটিপস.ইচটিএমএল #index- 29 মন্তব্যে 9 বলেছেন: পাইথন ২.৩ দিয়ে শুরু করে, সাজানোর () পদ্ধতিটি স্থিতিশীল হওয়ার নিশ্চয়তা রয়েছে। একটি বাছাই স্থিতিশীল হয় যদি এটি সমান তুলনাকারী উপাদানের আপেক্ষিক ক্রম পরিবর্তন না করার গ্যারান্টি দেয় - এটি একাধিক পাসে বাছাইয়ের জন্য সহায়ক (উদাহরণস্বরূপ, বিভাগ দ্বারা বাছাই করা, তারপরে বেতন গ্রেড দ্বারা)।
trapicki

এটি সঠিক নয় কারণ এটি তার জিজ্ঞাসা করা প্রশ্নের উত্তর দেয় না। তিনি প্রথম সূচক অনুসারে বাছাই করা একটি তালিকা চান এবং যেখানে প্রথম সূচীতে সম্পর্ক রয়েছে সে ক্ষেত্রে, তিনি দ্বিতীয় সূচকটি বাছাইয়ের মানদণ্ড হিসাবে ব্যবহার করতে চান। একটি স্থিতিশীল সাজান শুধুমাত্র গ্যারান্টি দেয় যে সমস্ত জিনিস সমান হচ্ছে, মূল অর্ডারটি হবে আইটেমগুলির প্রদর্শিত ক্রম।
জন

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

4
আমি মনে করি tuple()না যে দুটি যুক্তি (বা তার চেয়ে তিনটি, যদি আপনি গণনা করেন self) পেতে পারেন
ফিলিপ কোরিয়া

3
টিপল লাগে কেবল একটি যুক্তি নিতে পারে
Therelprashant

1
returnবিবৃতি return tuple((x[1], x[2]))বা সহজভাবে হওয়া উচিত return x[1], x[2]পড়ুন উত্তর @jaap আপনি বিভিন্ন নির্দেশাবলী মধ্যে বাছাই খুঁজছেন নিচে যদি
জো Kachikaran

… বা tuple(x[1:3]), আপনি যদি কেবল কোনও টুপল ডিসপ্লে তালিকার পরিবর্তে কোনও কারণে টুপল কনস্ট্রাক্টর ব্যবহার করতে চান x[1], x[2]। অথবা keyfunc = operator.itemgetter(1, 2)এবং নিজেই কোনও ফাংশন লিখবেন না।
abarnert

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

আমরা 2 বার লাম্বদা সহ বাছাই করতে পারি কারণ পাইথন সাজান স্থানে এবং স্থিতিশীল। এটি প্রথমে দ্বিতীয় উপাদান, x [1] অনুসারে তালিকাটিকে সাজিয়ে রাখবে। তারপরে, এটি প্রথম উপাদানটিকে x [0] (সর্বোচ্চ অগ্রাধিকার) বাছাই করবে।

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

এটি নিম্নলিখিত কাজগুলির সমতুল্য: কর্মচারী.সোর্ট (কী = ল্যাম্বদা এক্স: (এক্স [0], এক্স [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

নীচে ব্যবহার করে ডিক্টের তালিকা বাছাই করা তালিকা বেতনের হিসাবে প্রথম কলামে উতরমান ক্রমের তালিকা এবং বয়সের হিসাবে দ্বিতীয় কলামে সাজানো হবে

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

আউটপুট: [{'বেতন': 123, 'বয়স': 25}, salary 'বেতন': 123, 'বয়স': 23}]

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