Frage

Ich habe eine Liste von Sätzen:

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

Ich möchte s1 ∩ s2 ∩ s3 ...

Ich kann eine Funktion schreiben, es zu tun, indem sie eine Reihe von paarweise s1.intersection(s2) Durchführung etc.

Gibt es eine empfohlene, besser, oder integrierte Möglichkeit?

War es hilfreich?

Lösung

Von Python-Version 2.6 auf Sie mehrere Argumente an set.intersection() verwenden wie

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

Wenn die Sätze in einer Liste sind, bedeutet dies an:

u = set.intersection(*setlist)

Dabei gilt *a_list Liste Expansion

Andere Tipps

Wie von 2,6, nimmt set.intersection beliebig viele Iterables.

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

Klar set.intersection ist, was Sie hier wollen, aber den Fall, dass Sie jemals eine Verallgemeinerung von „nehmen Sie die Summe all dieser“, „nehmen das Produkt all dieser“, „nehmen Sie die xor all diese“, was du bist Suche ist die reduce-Funktion:

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}

Wenn Sie Python nicht 2.6 oder höher, die Alternative ist 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 können auch reduce verwenden:

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

Doch viele Python-Programmierer es nicht mögen, einschließlich Guido selbst :

  

Vor etwa 12 Jahren, Python Lambda aquired, reduzieren (), Filter () und Karte (), mit freundlicher Genehmigung von (glaube ich) ein Lisp-Hacker, die sie verpasst und legte Arbeits Patches. Aber trotz des PR-Wert, ich glaube, diese Funktionen von Python 3000 geschnitten werden sollte.

     

So, jetzt reduzieren (). Das ist eigentlich das, was ich immer am meisten gehasst habe, weil, abgesehen von ein paar Beispiele beteiligt + oder *, fast jedes Mal, wenn ich sehe eine Verringerung () mit einem nicht-triviale Funktion Argument, ich brauche zu greifen Stift und Papier Diagramm was tatsächlich in dieser Funktion zugeführt werden, bevor ich zu verstehen, was die Verringerung () tun soll. Also in meinem Kopf, die Anwendbarkeit reduzieren () ist ziemlich beschränkt auf assoziative Operatoren und in allen anderen Fällen ist es besser, explizit die Akkumulationsschleife zu schreiben.

Hier bin ich und bietet eine generische Funktion für mehrere Schnittmenge versucht, 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 könnte reduce nicht mögen, aber ich bin ein bisschen es gern:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top