Kümeler listesi var:
setlist = [s1,s2,s3...]
S1 ∩ s2 ∩ s3 istiyorum ...
Bir çift dizi gerçekleştirerek bunu yapmak için bir işlev yazabilirim s1.intersection(s2) vb .
Önerilen, daha iyi veya yerleşik bir yol var mı?
Kümeler listesi var:
setlist = [s1,s2,s3...]
S1 ∩ s2 ∩ s3 istiyorum ...
Bir çift dizi gerçekleştirerek bunu yapmak için bir işlev yazabilirim s1.intersection(s2) vb .
Önerilen, daha iyi veya yerleşik bir yol var mı?
Yanıtlar:
Üzerindeki Python sürüm 2.6'dan set.intersection(), aşağıdakiler gibi birden çok bağımsız değişken kullanabilirsiniz:
u = set.intersection(s1, s2, s3)
Kümeler bir listede bulunuyorsa, bu şu anlama gelir:
u = set.intersection(*setlist)
nerede *a_listolduğunu listesini genişletme
Not set.intersectionolduğunu değil statik bir yöntem, ancak bu listenin geri kalanı ile ilk setin kavşak uygulamak için işlevsel ifadesi kullanır. Dolayısıyla, argüman listesi boşsa bu başarısız olur.
2.6 itibariyle, set.intersectionkeyfi olarak birçok tekrarlanabilir.
>>> 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])
Açıkça set.intersectionburada istediğiniz şeydir, ancak "tüm bunların toplamını alın" genellemesine ihtiyacınız varsa, "tüm bunların ürününü alın", "tüm bunların xorunu alın", aradığınız şey reducefonksiyon:
from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
veya
print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
Python 2.6 veya daha üst sürümünüz yoksa, alternatif döngü için açık yazmaktır:
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])
Ayrıca şunları kullanabilirsiniz reduce:
set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])
Bununla birlikte, Guido'nun kendisi de dahil olmak üzere birçok Python programcısı bundan hoşlanmamaktadır :
Yaklaşık 12 yıl önce, Python, onları özleyen ve çalışma yamaları gönderen bir Lisp korsanının izniyle (inanıyorum) lambda, azaltma (), filtre () ve harita () 'yı satın aldı. Ancak, PR değerine rağmen, bu özelliklerin Python 3000'den kesilmesi gerektiğini düşünüyorum.
Şimdi azaltmak (). Bu aslında her zaman en çok nefret ettiğim şeydir, çünkü + veya * içeren birkaç örnekten ayrı olarak, neredeyse önemsiz olmayan bir işlev argümanı ile bir azaltma () çağrısı gördüğümde, kalem ve kağıt almam gerekiyor reduce () 'nin ne yapması gerektiğini anlamadan önce bu işleve gerçekten ne beslendiğini diyagramla. Bu yüzden aklımda, reduce () 'nin uygulanabilirliği hemen hemen ilişkisel operatörlerle sınırlıdır ve diğer tüm durumlarda birikim döngüsünü açıkça yazmak daha iyidir.
result.
Burada mevcut en iyi yöntemden yararlanmaya çalışırken çoklu set kavşağı için genel bir işlev sunuyorum:
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:])
Guido hoşlanmayabilir reduce, ama ben buna bayılıyorum :)
setsErişmeye sets[0]ve yakalamaya çalışmak yerine uzunluğunu kontrol etmelisiniz IndexError.
a_setson dönüşte kullanılır.
return reduce(sets[0], sets[1:]) if sets else set()?
try/ ' exceptEğer yapabilirsen kaçınılmalıdır. Bu bir kod kokusu, verimsiz ve diğer sorunları gizleyebilir.
reducebu durumda geçerli olan "ilişkisel işleçlerle sınırlı" olduğunu belirttiğini unutmayın .reduceanlaması çok zor, ama&o kadar da kötü değil.