2010-03-12 2 views

Antwort

8

Jemand fragt tatsächlich ein question hier nicht allzu lange Zeit, dass ich mit der Zip Erweiterungsmethode beantwortet, so ist es offensichtlich wichtig für einige Menschen. ;)

Eigentlich ist es eine ziemlich wichtige Operation für mathematische Algorithmen - Matrizen, Kurvenanpassung, Interpolation, Mustererkennung, diese Art von Sache. Auch sehr wichtig in Engineering-Anwendungen wie der digitalen Signalverarbeitung, bei der viel von dem, was Sie tun, mehrere Signale kombinieren oder lineare Transformationen auf sie anwenden - beide basieren auf dem Beispielindex und zippen damit. Das Zippen von zwei Sequenzen ist weit, viel schneller als das Sortieren und Verbinden basierend auf einem Schlüssel, insbesondere wenn Sie im Voraus wissen, dass die Sequenzen die gleiche Anzahl von Elementen haben und in der gleichen Reihenfolge sind.

Ich kann hier wegen meiner aktuellen Beschäftigung nicht in die Einzelheiten kommen, aber im Allgemeinen ist das auch wertvoll für Telemetriedaten - industriell, wissenschaftlich, so etwas.Oft haben Sie Zeitsequenzen von Daten aus Hunderten oder Tausenden von Punkten - parallele Quellen - und Sie müssen aggregieren, aber horizontal, über Geräte, nicht im Laufe der Zeit. Am Ende wollen Sie eine andere Zeitsequenz, aber mit der Summe oder dem Durchschnitt oder einem anderen Aggregat aller einzelnen Punkte.

Es mag wie eine einfache Art/Gruppe/Beitritt in SQL Server (zum Beispiel) klingen, aber es ist wirklich wirklich schwer, auf diese Weise effizient zu tun. Zum einen stimmen die Zeitstempel möglicherweise nicht genau überein, aber Sie interessieren sich nicht für Unterschiede von einigen Millisekunden, so dass Sie am Ende eine Ersatzschlüssel-/Zeilennummer generieren müssen und darauf gruppieren müssen - und natürlich die Ersatzreihennummer ist nichts mehr als die Zeit Index die Sie hatten bereits. Das Zippen ist einfach, schnell und unendlich parallelisierbar.

Ich weiß nicht, ob ichgrund es nennen würde, aber es ist es wichtig . Ich benutze die Reverse Methode auch nicht sehr oft, aber aus dem gleichen Grund bin ich froh, dass ich es nicht selbst schreiben muss bei den seltenen Gelegenheiten, wenn ich einen Bedarf dafür finde.

Einer der Gründe, warum es Ihnen nicht so nützlich erscheint, ist, dass .NET/C# 3.5 keine Tupel enthält. C# 4 does have tuples, und wenn Sie mit Tupeln arbeiten, Zippen wirklich ist eine grundlegende Operation, weil die Reihenfolge strikt durchgesetzt wird.

+0

Großartig, jetzt kann ich "Song A" nicht aus meinem Kopf bekommen ... –

+0

Hahaha, macht nichts, ich habe es gerade bekommen. : P – Aaronaught

+0

Es ist nicht, dass ich denke, dass es nicht nützlich scheint. Ich will nur wissen wie * oder * warum * es nützlich ist. – Cheeso

7

Sie können Sequenzen parallel statt nacheinander oder verschachtelt verarbeiten. Es gibt ... so viele Anwendungen dafür, dass sie mir momentan entkommen.

+4

Ich hoffe immer noch, dass Sie sich an einige erinnern ... – tanascius

+0

@tanascius: Das Schöne an Python ist, dass ich mich nicht an sie erinnern muss; sie zu machen, während ich weitergehe, ist eine vollkommen lebensfähige Strategie. –

7

Hier ist ein typischer Anwendungsfall für zip:

x = [1,2,3,4,5] 
y = [6,7,8,9,0] 

for a,b in zip(x,y): 
    print a, b 

Welche ausgeben würde:

1 6 
2 7 
3 8 
4 9 
5 0 
8

Ein Anwendungsfall:

>>> fields = ["id", "name", "location"] 
>>> values = ["13", "bill", "redmond"] 
>>> dict(zip(fields, values)) 
{'location': 'redmond', 'id': '13', 'name': 'bill'} 

Versuchen Sie dies ohne Reißverschluss tun ...

+0

dict ([(Felder [i], Werte [i]) für i in Bereich (min (len (Felder), len (Werte)))]) – tixxit

+3

@tixxit: Ich wollte nicht sagen, dass es unmöglich war ohne zip, ich meinte nur weniger lesbar/elegant und auf jeden Fall mehr verbose ;-) – ChristopheD

+0

Und natürlich, wenn wir das obige Listenverständnis verallgemeinern, bekommen wir nur die zip-Funktion wieder: def myzip (* args): zurück [ Tupel (args [j] [i] für j im Bereich (len (args))) für i im Bereich (min (len (args [j]) für j im Bereich (len (args))))] – tixxit

11

zip ist nützlich, wenn Sie li Sie können mehrere Iterables gleichzeitig durchlaufen, was in Python ein relativ häufiges Szenario ist.

Ein reales Szenario, in dem zip für mich nützlich ist, ist, wenn Sie ein M-by-N-Array haben und Spalten anstelle von Zeilen betrachten möchten. Zum Beispiel:

>>> five_by_two = ((0, 1), (1, 2), (2, 3), (3, 4), (4, 5)) 
>>> two_by_five = tuple(zip(*five_by_two)) 
>>> two_by_five 
((0, 1, 2, 3, 4), (1, 2, 3, 4, 5)) 
+0

cool, wusste nicht, dass Sie mehr als 2 Gruppen zippen können. Ist das neu in Python 3 oder funktioniert das in 2.x? – Davy8

+0

Yup, ich habe das oft benutzt. @ Davy8: Ja, es funktioniert definitiv in 2.x. Ich vergesse, wenn der Operator '*' hinzugefügt wurde, aber Sie hätten wahrscheinlich 'apply()' verwenden können, um den gleichen Effekt auch in Python 1.x zu erhalten. –

+0

@ Davy8 es funktioniert in 2.x. Wenn zip mit * verwendet wird, wird es üblicherweise als unzip bezeichnet. –

2

Hier ist ein Fall, in dem ich zip() zu nützlichem Effekt verwendet wird, in einer Python-Klasse für den Vergleich von Versionsnummern:

class Version(object): 

    # ... snip ... 

    def get_tuple(self): 
     return (self.major, self.minor, self.revision) 

    def compare(self, other): 
     def comp(a, b): 
      if a == '*' or b == '*': 
       return 0 
      elif a == b: 
       return 0 
      elif a < b: 
       return -1 
      else: 
       return 1 
     return tuple(comp(a, b) for a, b in zip(self.get_tuple(), Version(other).get_tuple())) 

    def is_compatible(self, other): 
     tup = self.compare(other) 
     return (tup[0] == 0 and tup[1] == 0) 

    def __eq__(self, other): 
     return all(x == 0 for x in self.compare(other)) 

    def __ne__(self, other): 
     return any(x != 0 for x in self.compare(other)) 

    def __lt__(self, other): 
     for x in self.compare(other): 
      if x < 0: 
       return True 
      elif x > 0: 
       return False 
     return False 

    def __gt__(self, other): 
     for x in self.compare(other): 
      if x > 0: 
       return True 
      elif x < 0: 
       return False 
     return False 

ich zip() denken, gekoppelt mit all() und any(), macht den Vergleich Operator-Implementierungen besonders klar und elegant. Sicher, es hätte ohne zip() gemacht werden können, aber dann könnte das gleiche über praktisch jede Sprachfunktion gesagt werden.

+0

@Daniel Pryden: Vorschlag: 'wenn x> 0: return True | elif x> 0: Rückgabe Falsch | return False 'könnte einfach' return x> 0' sein – ChristopheD

+0

@ChristopheD: Nein, weil es in einer 'for' Schleife über den punktierten Teilen ist. Wenn der aktuelle punktierte Teil größer ist, dann wissen wir, dass das Ganze größer ist; wenn der aktuelle punktierte Teil kleiner ist, dann wissen wir, dass das Ganze weniger ist; Wenn aber der aktuelle gepunktete Teil gleich ist, müssen wir uns den nächsten gepunkteten Teil ansehen. Das heißt, es gibt ein Formatierungsproblem mit dem Einzug dieser letzten Zeile ... gib mir eine Sekunde und ich werde das beheben. –

+0

Ok, das macht jetzt Sinn ;-) – ChristopheD

3

Es ist praktisch an verschiedenen Orten. Mein Favorit, von http://norvig.com/python-iaq.html wird zur Umsetzung eine Matrix:

>>> x = [ [1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]] 
>>> zip(*x) 
[(1, 6, 11), (2, 7, 12), (3, 8, 13), (4, 9, 14), (5, 10, 15)] 
+0

http://stackoverflow.com/questions/2429692/what-is-the-purpose-of-a-zip-function-as-in-python-or-c-4 -0/2429737 # 2429737 – Ponkadoodle

+0

Sorry, Cross-Editing. –