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_list
olduğunu listesini genişletme
Not set.intersection
olduğ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.intersection
keyfi 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.intersection
burada 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 reduce
fonksiyon:
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 :)
sets
Erişmeye sets[0]
ve yakalamaya çalışmak yerine uzunluğunu kontrol etmelisiniz IndexError
.
a_set
son dönüşte kullanılır.
return reduce(sets[0], sets[1:]) if sets else set()
?
try
/ ' except
Eğer yapabilirsen kaçınılmalıdır. Bu bir kod kokusu, verimsiz ve diğer sorunları gizleyebilir.
reduce
bu durumda geçerli olan "ilişkisel işleçlerle sınırlı" olduğunu belirttiğini unutmayın .reduce
anlaması çok zor, ama&
o kadar da kötü değil.