2010-03-29 19 views

Antwort

278

Von Python-Version 2.6 auf mehrere Argumente zu set.intersection(), wie

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

Wenn die Sätze sind in einer Liste verwenden können, bedeutet dies zu:

u = set.intersection(*setlist) 

wo *a_listlist expansion ist

+0

Kannst du mir bitte erklären oder auf die relevante Dokumentation verweisen für was "* setlist" hier bedeutet? (Genauer gesagt, was macht der Stern?) Danke! – PurpleVermont

+6

Für jeden anderen, der die gleiche Frage wie ich haben könnte, fand ich die Antwort hier: http://StackOverflow.com/Questions/400739/what-does-asterisk-mean-in-python – PurpleVermont

10

Wenn Sie nicht Python 2.6 oder höher, ist die Alternative eine explizite for-Schleife zu schreiben:

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]) 

Sie auch reduce verwenden können:

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

jedoch viele Python-Programmierer nicht mögen es, :

Vor etwa 12 Jahren, Python erwarb Lambda, reduzieren(), fil ter() und map() mit freundlicher Genehmigung von (glaube ich) einem Lisp-Hacker, der sie vermisste und Arbeitsflicken einreichte. Aber, trotz der PR-Wert, denke ich, diese Funktionen sollten von Python 3000 geschnitten werden.

So jetzt reduzieren(). Das ist eigentlich das, was ich immer am meisten gehasst habe, denn abgesehen von ein paar Beispielen mit + oder * muss ich fast jedes Mal, wenn ich einen reduce() -Aufruf mit einem nicht-trivialen Funktionsargument sehe, Stift und Papier greifen Diagramm, was tatsächlich in diese Funktion eingegeben wird, bevor ich verstehe, was die reduce() tun soll. In meinen Augen ist die Anwendbarkeit von reduce() ziemlich stark auf assoziative Operatoren beschränkt, und in allen anderen Fällen ist es besser, die Akkumulationsschleife explizit auszugeben.

+8

Beachten Sie, dass Guido sagt 'reduce' Verwendung ist "beschränkt sich auf assoziative Operatoren", die in diesem Fall anwendbar ist. "Reduzieren" ist oft schwer zu verstehen, aber für '&' ist nicht so schlimm. –

+0

[set_list und reduce (set.intersection, set_list) '] (http://stackoverflow.com/a/1404146/4279) – jfs

+0

Schauen Sie sich https://www.python.org/doc/essays/list2str/ an nützliche Optimierungen, die reduzieren. Es kann im Allgemeinen sehr schön verwendet werden, um Listen, Sets, Strings usw. zu erstellen. Einen Blick wert ist auch https://github.com/EntilZha/PyFunctional – Andreas

41

Ab 2.6 nimmt set.intersection beliebig viele iterierbar.

>>> 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]) 
1

Hier bin ich eine generische Funktion für mehrere Schnittmenge bietet versuchen, die Vorteile der besten Methode zu nehmen zur Verfügung:

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 reduce nicht mögen könnte, aber ich bin ein bisschen es gern :)

+0

Sie sollten die Länge von überprüfen setzt, statt auf 'sets [0]' zuzugreifen und den 'IndexError' einzufangen. – bfontaine

+0

Dies ist keine einfache Überprüfung; 'a_set' wird bei der endgültigen Rückgabe verwendet. – tzot

+0

Kannst du 'return reduce (setzt [0], setzt [1:]) wenn set else set()'? – bfontaine

11

Offensichtlich set.intersection ist was du willst hier, aber falls du jemals eine Verallgemeinerung von "nimm die Summe von all diesen", "nimm das Produkt von all diesen", "nimm die xor von all diesen", Was Sie suchen, ist die reduce f Salbung:

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

oder

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