কাস্টম পাইথন তালিকা বাছাই


98

আমি আমার কিছু পুরানো কোড রিফ্যাক্টর করছিলাম এবং এটির জুড়ে এসেছি:

alist.sort(cmp_items)

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    elif a.foo == b.foo:
        return 0
    else:
        return -1

কোডটি কাজ করে (এবং আমি এটি প্রায় 3 বছর আগে লিখেছিলাম!) তবে পাইথন ডক্সে এই জিনিসটি কোথাও নথিভুক্ত করা খুঁজে পাচ্ছি না এবং প্রত্যেকে sorted()কাস্টম বাছাইয়ের প্রয়োগ করতে ব্যবহার করে। কেউ ব্যাখ্যা করতে পারে কেন এটি কাজ করে?


sorted()এবং sort()অনেক একইভাবে কাস্টম বাছাইয়ের অফার, কনভেনশন কল করার মধ্যে পার্থক্য মডুলো।
রাসেল বোরোগোভ

4
প্রকৃতপক্ষে, যা ঘটে তা হ'ল keyকোনও cmpফাংশনটি পাস করার চেয়ে পরামিতি ব্যবহার করা পছন্দ হয় । (পরবর্তীতে পাইথন 3
তেও

এটি এক ধরণের অস্পষ্ট, নির্ভর করে তালিকার আইটেমগুলি কী ছিল; আপনার কোডে তাদের একটি বৈশিষ্ট্য থাকা দরকার foo, অন্যথায় এটি ফুরিয়ে যায়। __lt__()আপনার শ্রেণীর জন্য একটি কাস্টম পদ্ধতি সংজ্ঞায়িত করা আরও ভাল , তারপরে sorted()এবং list.sort()বাক্সের বাইরে কাজ করবে। (BTW, সংজ্ঞায়িত করতে আর প্রয়োজন বস্তু __cmp__(), শুধু __lt__()এই দেখুন
smci

উত্তর:


60

এটি এখানে নথিভুক্ত ।

তুলনা নিয়ন্ত্রণ করার জন্য বাছাই () পদ্ধতিটি alচ্ছিক যুক্তি গ্রহণ করে।

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


ধন্যবাদ মাইল ৮২ আমি এখানে যাচাই করছিলাম এবং এটি পদ্ধতি পদ্ধতিতে স্বাক্ষর করতে পারলাম না ডকস.পিথন.আর
লোরেঞ্জো

আপনার লিঙ্ক করা পৃষ্ঠায় আমি একই পাঠ্যটি দেখতে পাচ্ছি না। ডকুমেন্টেশন পরিবর্তন হয়েছে। এছাড়া যখন আমি ব্যবহারের চেষ্টা cmp, আমি পেতে TypeError: 'cmp' is an invalid keyword argument for this function। এখানে কি হচ্ছে?
হ্যালো গুডবাই

4
@ হেলো গুডবাইয়ের সাজান () এর পাইথন ৩ তে কোনও সিএমপি যুক্তি নেই This এটি ডেক্স লিঙ্কটি পাইথন ২ এর জন্য ছিল তখন এটি একটি পুরানো উত্তর You আপনি এখানে পুরানো ডক্সটি খুঁজে পেতে পারেন বা এটি সম্পর্কে আরও পড়তে পারেন এখানে । আপনি যদি পাইথন 3 ব্যবহার করেন তবে পরিবর্তে মূল যুক্তিটি ব্যবহার করুন।
মাইল 82 ই

এবং যদি আপনি আসলে তুলনা ফাংশন সরবরাহ করতে চান? আমি পৃথক অক্ষরগুলি অন্যথায় কীভাবে আচরণ করা হয় তার সমানভাবে চিহ্নগুলিতে সংখ্যার সাথে একটি স্ট্রিংয়ে (যে কোনও দৈর্ঘ্যের, লোভযুক্তভাবে বেছে নেওয়া) প্রতীক হিসাবে আচরণ করতে চাই। আমি যদি তুলনামূলক ফাংশন সরবরাহ করতে পারি তবে কীভাবে তুচ্ছভাবে এটি অর্জন করতে হয় তা আমি জানি তবে আমার কী ফাংশন অবশ্যই সরবরাহ করতে হবে তা নয়। কেন এই পরিবর্তন করা হয়েছিল?
হ্যালো গুডবাই

আমার ধারণা, স্ট্রিংয়ে থাকা প্রতিটি নম্বর যদি এনকোডিং ব্যবহার করে এনকোড করা থাকে যা লেভেনস্টেইন কোডিংয়ের মতো নম্বরগুলিকে ডিক্সিকোগ্রাফিকভাবে অর্ডার করে তবে এটি অর্জন করা সম্ভব । তবে আমি এটিকে আরও সত্য হিসাবে বিবেচনা করি sortযা পাইথন 3-তে যুক্তি হিসাবে তুলনা ফাংশন গ্রহণ করে না এবং আমি আসলে যা করতে চাই তা হিসাবে নয় ।
হ্যালোগুডবাই

108

পার্শ্ব নোট হিসাবে, এখানে একই বাছাইয়ের আরও কার্যকর বিকল্প:

alist.sort(key=lambda x: x.foo)

বা বিকল্পভাবে:

import operator
alist.sort(key=operator.attrgetter('foo'))

কীভাবে বাছাই হচ্ছে তা পরীক্ষা করে দেখুন এটি খুব দরকারী।


4
অপারেটর সম্পর্কে টিআইএল, খুব দরকারী।
ffledgling

16

ঠিক যেমন উদাহরণ। আপনি এই তালিকাটি বাছাই করতে চান।

[('c', 2), ('b', 2), ('a', 3)]

আউটপুট:

[('a', 3), ('b', 2), ('c', 2)]

আপনি দ্বিতীয় আইটেম দ্বারা tuples বাছাই করা উচিত, তারপরে প্রথম:

def letter_cmp(a, b):
    if a[1] > b[1]:
        return -1
    elif a[1] == b[1]:
        if a[0] > b[0]:
            return 1
        else:
            return -1
    else:
        return 1

তারপরে এটিকে একটি মূল ফাংশনে রূপান্তর করুন:

from functools import cmp_to_key
letter_cmp_key = cmp_to_key(letter_cmp))

এখন আপনি আপনার কাস্টম বাছাই অর্ডার ব্যবহার করতে পারেন:

[('c', 2), ('b', 2), ('a', 3)].sort(key=letter_cmp_key)

4
এটি কীভাবে তালিকাটি বাছাই করতে পারে?
ক্যামেরন ভিক্ষু

4
@ ক্যামেরনমোনস আপনার লিস্ট.সোর্ট (লেটার_সিএমপি)
কাবাব-কেস

7

পাইথন 3 এ এটি কাজ করে না।

পুরানো শৈলীর তুলনা ফাংশনগুলি কাজ করতে আপনি ফান্টুলগুলি cmp_to_key ব্যবহার করতে পারেন।

from functools import cmp_to_key

def cmp_items(a, b):
    if a.foo > b.foo:
        return 1
    elif a.foo == b.foo:
        return 0
    else:
        return -1

cmp_items_py3 = cmp_to_key(cmp_items)

alist.sort(cmp_items_py3)

1

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

l = [(2, 3), (3, 4), (2, 4)]
l.sort(key = lambda x: (-x[0], -x[1]) )
print(l)
l.sort(key = lambda x: (x[0], -x[1]) )
print(l)

আউটপুট হবে

[(3, 4), (2, 4), (2, 3)]
[(2, 4), (2, 3), (3, 4)]

আমরা টিউপল ফর্ম্যাটে সরবরাহিত পরামিতিগুলির ক্রমের ভিত্তিতে আউটপুটটি সাজানো হবে


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