একাধিক বৈশিষ্ট্য অনুসারে একটি তালিকা সাজান?


454

আমার তালিকাগুলির একটি তালিকা রয়েছে:

[[12, 'tall', 'blue', 1],
[2, 'short', 'red', 9],
[4, 'tall', 'blue', 13]]

যদি আমি এক উপাদান এটি অনুসারে বাছাইয়ের জন্য চেয়েছিলেন, লম্বা / শর্ট উপাদান বলে, আমি মাধ্যমে এটা করতে পারে s = sorted(s, key = itemgetter(1))

যদি আমি লম্বা / সংক্ষিপ্ত এবং রঙ উভয় দ্বারা বাছাই করতে চাই , তবে আমি প্রতিটি উপাদানটির জন্য একবার, দু'বার বাছাই করতে পারতাম, তবে কি আরও দ্রুত উপায় আছে?



8
আপনি যদি তালিকার পরিবর্তে টিপলগুলি ব্যবহার করেন, অজগরটি যখন আপনি চালাবেন তখন বাম থেকে ডানে প্রবেশের মাধ্যমে বাছাই করে sort। যে sorted([(4, 2), (0, 3), (0, 1)]) == [(0, 1), (0, 3), (4, 2)],।
মতিন উলহাক

উত্তর:


769

একটি কী একটি ফাংশন হতে পারে যা একটি টিপল দেয়:

s = sorted(s, key = lambda x: (x[1], x[2]))

অথবা আপনি এটি ব্যবহার করে একই অর্জন করতে পারেন itemgetter(যা দ্রুত এবং পাইথন ফাংশন কলকে এড়িয়ে চলে):

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

এবং লক্ষ্য করুন যে এখানে আপনি sortব্যবহার sortedএবং তারপরে পুনরায় নিয়োগের পরিবর্তে ব্যবহার করতে পারেন :

s.sort(key = operator.itemgetter(1, 2))

20
সময় থেকে সম্পূর্ণতার জন্য: আমার জন্য প্রথমে আমাদের প্রতি লুপে 6 জন এবং দ্বিতীয়টি লুপ প্রতি 4.4 দেয়
ব্রায়ান লারসেন

10
প্রথমটিকে আরোহণের এবং দ্বিতীয়টিটি নামার কিছুর জন্য কোনও উপায় আছে? (ধরে নিন উভয় বৈশিষ্ট্যই স্ট্রিং, তাই কোনও -পূর্ণসংখ্যার জন্য যোগ করার মতো হ্যাক নেই )
মার্টিন থোমা

73
আমি যদি revrse=Trueকেবলমাত্র প্রয়োগ করতে চাই তবে কী x[1]সম্ভব?
অ্যামিথ

28
@ মুজ, @ অ্যামিথ, কেবল একটি বৈশিষ্ট্যের বিপরীতে, আপনি দু'বার বাছাই করতে পারেন: প্রথমে মাধ্যমিকের s = sorted(s, key = operator.itemgetter(2))পরে প্রাথমিক দ্বারা s = sorted(s, key = operator.itemgetter(1), reverse=True)আদর্শ নয়, তবে কাজ করে।
টমকসনসেল

52
@ অ্যামথ বা অন্য কোনও বিকল্প, কীটি যদি সংখ্যাটি হয় তবে এটিকে বিপরীত করে তোলার জন্য, আপনি এটি দ্বারা একাধিক করতে পারেন -1
সার্জ 11

37

আমি নিশ্চিত নই যে এটি সর্বাধিক পাইথোনিক পদ্ধতি কিনা ... আমার কাছে টিপলগুলির একটি তালিকা ছিল যা পূর্বে পূর্ণসংখ্যার মানগুলি এবং দ্বিতীয় বর্ণানুক্রমিকভাবে অবতরণ করে 1 ম বাছাই করা দরকার needed এর জন্য পূর্ণসংখ্যার সাজানোর বিপরীত হওয়া প্রয়োজন তবে বর্ণমালা অনুসারে নয়। আমার সমাধানটি এখানে ছিল: (বিটিডব্লিউর পরীক্ষায় উড়ে যাওয়ার সময়, আমি জানতাম না যে আপনি বাসা বাছাই করতে পারবেন)

a = [('Al', 2),('Bill', 1),('Carol', 2), ('Abel', 3), ('Zeke', 2), ('Chris', 1)]  
b = sorted(sorted(a, key = lambda x : x[0]), key = lambda x : x[1], reverse = True)  
print(b)  
[('Abel', 3), ('Al', 2), ('Carol', 2), ('Zeke', 2), ('Bill', 1), ('Chris', 1)]

12
যেহেতু ২ য় সংখ্যা, এটি এটি কাজ করতে কাজ b = sorted(a, key = lambda x: (-x[1], x[0]))করে যা কোন মানদণ্ডে প্রথমে প্রয়োগ হয় তার উপর এটি আরও দৃশ্যমান। দক্ষতার জন্য আমি নিশ্চিত নই, কারও সময়সীমার দরকার।
আন্দ্রে-নিকুলি পেট্রে

4

এটি প্রদর্শিত হয় আপনি একটি এর listপরিবর্তে একটি ব্যবহার করতে পারেন tuple। আপনি আরও বেশি গুরুত্বপূর্ণ হয়ে ওঠেন আমি মনে করি আপনি যখন কোনও তালিকার / যাদুকরের 'ম্যাজিক সূচী' এর পরিবর্তে বৈশিষ্ট্যগুলি দখল করছেন।

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

তাই প্রথমে আমি একটি সহায়ক পদ্ধতি সংজ্ঞায়িত করেছি

def attr_sort(self, attrs=['someAttributeString']:
  '''helper to sort by the attributes named by strings of attrs in order'''
  return lambda k: [ getattr(k, attr) for attr in attrs ]

তারপরে এটি ব্যবহার করতে

# would defined elsewhere but showing here for consiseness
self.SortListA = ['attrA', 'attrB']
self.SortListB = ['attrC', 'attrA']
records = .... #list of my objects to sort
records.sort(key=self.attr_sort(attrs=self.SortListA))
# perhaps later nearby or in another function
more_records = .... #another list
more_records.sort(key=self.attr_sort(attrs=self.SortListB))

এটি তৈরি করা ল্যাম্বদা ফাংশনটি তালিকাটি অনুসারে বাছাই করবে object.attrAএবং তারপরে object.attrBধরে objectনেওয়া হবে যে সরবরাহ করা স্ট্রিংয়ের সাথে মিল রয়েছে ter আর দ্বিতীয় ক্ষেত্রে দ্বারা বাছাই হবে object.attrCতারপর object.attrA

এটি আপনাকে গ্রাহক, ইউনিট পরীক্ষা দ্বারা ভাগ করে নেওয়ার বাছাইয়ের পছন্দগুলিও সম্ভাব্যভাবে উন্মোচিত করার অনুমতি দেয় বা তাদের পক্ষে সম্ভবত আপনাকে জানায় যে তারা আপনার এপিআইতে কিছু অপারেশনের জন্য কীভাবে বাছাই করতে চান কেবল আপনাকে একটি তালিকা দিতে হবে এবং না আপনার পিছনের শেষ প্রয়োগে তাদের সংযুক্ত করে


চমৎকার কাজ. যদি বৈশিষ্ট্যগুলি বিভিন্ন ক্রমে বাছাই করা যায় তবে কী হবে? ধরুন, অ্যাট্রিএ আরোহণ এবং অ্যাটর্বি অবতরণ অনুসারে বাছাই করা উচিত? এর উপরে কি দ্রুত সমাধান পাওয়া যায়? ধন্যবাদ!
mhn_namak

3

বহু বছর দেরী পক্ষের কাছে কিন্তু আমি চাই উভয় 2 মানদণ্ডের উপর সাজানোর এবং ব্যবহার reverse=True। যদি অন্য কেউ জানতে চান যে আপনি কীভাবে আপনার মানদণ্ড (ফাংশনগুলি) প্রথম বন্ধনে আবদ্ধ করতে পারেন:

s = sorted(my_list, key=lambda i: ( criteria_1(i), criteria_2(i) ), reverse=True)

1

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

এর সুবিধাটি হ'ল এটি ডেটা দিয়ে এককভাবে পাস করে যা অন্য পদ্ধতিগুলির মতো পূর্ববর্তী বাছাইয়ের নয়। আর একটি বিষয় এটি স্থানে বাছাই করে, যেখানে সাজানো মনে হয় একটি অনুলিপি তৈরি করে।

আমি এটি একটি র‌্যাঙ্ক ফাংশন লিখতে ব্যবহার করেছি, এটি ক্লাসগুলির একটি তালিকার সাথে তালিকায় রয়েছে যেখানে প্রতিটি বস্তু একটি গ্রুপে রয়েছে এবং এর স্কোর ফাংশন রয়েছে, তবে আপনি কোনও বৈশিষ্ট্যের তালিকা যুক্ত করতে পারেন। আন-ল্যাম্বদা-জাতীয় নোট করুন, যদিও কোনও সেটার কল করতে ল্যাম্বডা ব্যবহারের হ্যাকিশ ব্যবহার। তালিকার অংশটি তালিকার একটি অ্যারের জন্য কাজ করবে না, তবে বাছাই করবে।

#First, here's  a pure list version
my_sortLambdaLst = [lambda x,y:cmp(x[0], y[0]), lambda x,y:cmp(x[1], y[1])]
def multi_attribute_sort(x,y):
    r = 0
    for l in my_sortLambdaLst:
        r = l(x,y)
        if r!=0: return r #keep looping till you see a difference
    return r

Lst = [(4, 2.0), (4, 0.01), (4, 0.9), (4, 0.999),(4, 0.2), (1, 2.0), (1, 0.01), (1, 0.9), (1, 0.999), (1, 0.2) ]
Lst.sort(lambda x,y:multi_attribute_sort(x,y)) #The Lambda of the Lambda
for rec in Lst: print str(rec)

অবজেক্টের একটি তালিকা র‌্যাঙ্ক করার একটি উপায় এখানে

class probe:
    def __init__(self, group, score):
        self.group = group
        self.score = score
        self.rank =-1
    def set_rank(self, r):
        self.rank = r
    def __str__(self):
        return '\t'.join([str(self.group), str(self.score), str(self.rank)]) 


def RankLst(inLst, group_lambda= lambda x:x.group, sortLambdaLst = [lambda x,y:cmp(x.group, y.group), lambda x,y:cmp(x.score, y.score)], SetRank_Lambda = lambda x, rank:x.set_rank(rank)):
    #Inner function is the only way (I could think of) to pass the sortLambdaLst into a sort function
    def multi_attribute_sort(x,y):
        r = 0
        for l in sortLambdaLst:
            r = l(x,y)
            if r!=0: return r #keep looping till you see a difference
        return r

    inLst.sort(lambda x,y:multi_attribute_sort(x,y))
    #Now Rank your probes
    rank = 0
    last_group = group_lambda(inLst[0])
    for i in range(len(inLst)):
        rec = inLst[i]
        group = group_lambda(rec)
        if last_group == group: 
            rank+=1
        else:
            rank=1
            last_group = group
        SetRank_Lambda(inLst[i], rank) #This is pure evil!! The lambda purists are gnashing their teeth

Lst = [probe(4, 2.0), probe(4, 0.01), probe(4, 0.9), probe(4, 0.999), probe(4, 0.2), probe(1, 2.0), probe(1, 0.01), probe(1, 0.9), probe(1, 0.999), probe(1, 0.2) ]

RankLst(Lst, group_lambda= lambda x:x.group, sortLambdaLst = [lambda x,y:cmp(x.group, y.group), lambda x,y:cmp(x.score, y.score)], SetRank_Lambda = lambda x, rank:x.set_rank(rank))
print '\t'.join(['group', 'score', 'rank']) 
for r in Lst: print r
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.