একাধিক সেট ছেদ করার সর্বোত্তম উপায়?


265

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

setlist = [s1,s2,s3...]

আমি এস 1 ∩ এস 2 ∩ এস 3 চাই ...

আমি জুটিওয়ালা s1.intersection(s2)ইত্যাদি ধারাবাহিক সম্পাদন করে এটি করার জন্য একটি ফাংশন লিখতে পারি

কোন প্রস্তাবিত, ভাল, বা অন্তর্নির্মিত উপায় আছে?

উত্তর:


453

পাইথন সংস্করণ ২.6 থেকে আপনি একাধিক যুক্তি set.intersection()পছন্দ করতে পারেন , পছন্দ করতে পারেন

u = set.intersection(s1, s2, s3)

যদি সেটগুলি কোনও তালিকায় থাকে তবে এটি অনুবাদ করে:

u = set.intersection(*setlist)

যেখানে *a_listহয় তালিকা সম্প্রসারণ

লক্ষ্য করুন set.intersectionহয় না একটি স্ট্যাটিক পদ্ধতি, কিন্তু এই তালিকার বাকি সঙ্গে প্রথম সেট ছেদ আবেদন করতে কার্মিক স্বরলিপি ব্যবহার করে। সুতরাং যুক্তি তালিকাটি খালি থাকলে এটি ব্যর্থ হবে।


64

২.6 হিসাবে, set.intersectionনির্বিচারে অনেকগুলি পুনরাবৃত্তি গ্রহণ করে।

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 4, 6])
>>> s1 & s2 & s3
set([2])
>>> s1.intersection(s2, s3)
set([2])
>>> sets = [s1, s2, s3]
>>> set.intersection(*sets)
set([2])

24

set.intersectionআপনি এখানে যা চান তা স্পষ্টতই , তবে আপনার যদি কখনও "এই সমস্তের যোগফল গ্রহণ করুন", "এইগুলির পণ্য গ্রহণ করুন", "এই সকলের জোর নিন", আপনি যা খুঁজছেন তা সাধারণীকরণের প্রয়োজন হয় reduceফাংশন:

from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

অথবা

print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

12

যদি আপনার কাছে পাইথন ২.6 বা তার বেশি না থাকে তবে বিকল্পটি লুপের জন্য একটি স্পষ্ট লিখতে হবে:

def set_list_intersection(set_list):
  if not set_list:
    return set()
  result = set_list[0]
  for s in set_list[1:]:
    result &= s
  return result

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print set_list_intersection(set_list)
# Output: set([1])

আপনি এটি ব্যবহার করতে পারেন reduce:

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])

তবে অনেক পাইথন প্রোগ্রামার এটিকে অপছন্দ করেন, নিজে গুডো সহ :

প্রায় 12 বছর আগে পাইথন ল্যাম্বডা অর্জন, কমিয়ে (), ফিল্টার () এবং মানচিত্র () লিস্প হ্যাকারের সৌজন্যে (আমি বিশ্বাস করি) সেগুলি মিস করে এবং কার্যকরী প্যাচগুলি জমা দিয়েছিলেন। তবে, PR মান সত্ত্বেও, আমি মনে করি এই বৈশিষ্ট্যগুলি পাইথন 3000 থেকে কাটা উচিত।

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


8
নোট করুন যে গুইডো বলেছেন যে ব্যবহারটি reduce"এসোসিয়েটিভ অপারেটরগুলির মধ্যে সীমাবদ্ধ", যা এই ক্ষেত্রে প্রযোজ্য। reduceখুব প্রায়ই খুঁজে বের করা কঠিন, তবে &এটি এতটা খারাপ নয়।
মাইক গ্রাহাম


হ্রাস জড়িত দরকারী অপ্টিমাইজেশন জন্য python.org/doc/essays/list2str দেখুন । এটি সাধারণত তালিকা, সেট, স্ট্রিং ইত্যাদি তৈরিতে বেশ সুন্দরভাবে ব্যবহার করা যেতে পারে, এর চেয়ে বেশি মূল্য দেখুন github.com/EntilZha/PYFunctional
Andreas

নোট আপনি resultখালি যখন আপনার লুপটি ভেঙে অপ্টিমাইজ করতে পারেন ।
bfontaine

1

এখানে আমি উপলব্ধ সেরা পদ্ধতির সুবিধা নেওয়ার চেষ্টা করে একাধিক সেট ছেদ করার জন্য একটি জেনেরিক ফাংশন দিচ্ছি:

def multiple_set_intersection(*sets):
    """Return multiple set intersection."""
    try:
        return set.intersection(*sets)
    except TypeError: # this is Python < 2.6 or no arguments
        pass

    try: a_set= sets[0]
    except IndexError: # no arguments
        return set() # return empty set

    return reduce(a_set.intersection, sets[1:])

গিডো অপছন্দ করতে পারে reduceতবে আমি এটির এক প্রকারের :)


আপনি দৈর্ঘ্য পরীক্ষা করা উচিত setsঅ্যাক্সেস করার চেষ্টা পরিবর্তে sets[0]এবং সংক্রামক IndexError
bfontaine

এটি কোনও সরল চেক নয়; a_setচূড়ান্ত রিটার্নে ব্যবহৃত হয়।
tzot

তুমি কি পারবে না return reduce(sets[0], sets[1:]) if sets else set()?
bfontaine

হ্যাঁ, ধন্যবাদ কোডটি পরিবর্তন করা উচিত কারণ আপনি যদি পারেন তবে একটি try/ এর উপর নির্ভর exceptকরা এড়ানো উচিত। এটি একটি কোড গন্ধ, অকার্যকর এবং অন্যান্য সমস্যাগুলি আড়াল করতে পারে।
bfontaine

0

জিন-ফ্রানসোইস ফ্যাব্রে সেটডিন্টিকেশন (* list_of_sets) উত্তরটি অবশ্যই সর্বাধিক পাইথোনিক এবং যথাযথভাবে গৃহীত উত্তর।

যারা হ্রাস ব্যবহার করতে চান তাদের জন্য নিম্নলিখিতগুলিও কাজ করবে:

reduce(set.intersection, list_of_sets)

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