it-swarm.com.de

Iteration über alle zwei Elemente in einer Liste

Wie mache ich eine for-Schleife oder ein Listenverständnis, so dass ich bei jeder Wiederholung zwei Elemente bekomme?

l = [1,2,3,4,5,6]

for i,k in ???:
    print str(i), '+', str(k), '=', str(i+k)

Ausgabe:

1+2=3
3+4=7
5+6=11
160
jackhab

Sie benötigen eine pairwise() (oder grouped()) Implementierung.

Für Python 2:

from itertools import izip

def pairwise(iterable):
    "s -> (s0, s1), (s2, s3), (s4, s5), ..."
    a = iter(iterable)
    return izip(a, a)

for x, y in pairwise(l):
   print "%d + %d = %d" % (x, y, x + y)

Oder allgemeiner:

from itertools import izip

def grouped(iterable, n):
    "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
    return izip(*[iter(iterable)]*n)

for x, y in grouped(l, 2):
   print "%d + %d = %d" % (x, y, x + y)

In Python 3 können Sie izip durch die eingebaute Funktion Zip() ersetzen und die import löschen.

Alles Gute an martineau für seine Antwort an meine Frage , ich habe festgestellt, dass dies sehr effizient ist, da es nur einmal über die Liste iteriert und keine erstellt unnötige Listen im Prozess. 

NB: Dies sollte nicht mit dem pairwise - Rezept in Pythons eigenem itertools documentation verwechselt werden, was s -> (s0, s1), (s1, s2), (s2, s3), ..., as ergibt wies in den Kommentaren auf @lazyr hin.

196
Johnsyweb

Nun, du brauchst Tupel von 2 Elementen, also

data = [1,2,3,4,5,6]
for i,k in Zip(data[0::2], data[1::2]):
    print str(i), '+', str(k), '=', str(i+k)

Woher:

  • data[0::2] bedeutet, eine Teilmenge von Elementen zu erstellen, die (index % 2 == 0)
  • Zip(x,y) erstellt eine Tupel-Sammlung aus den Indexelementen x und y.
150
Margus
>>> l = [1,2,3,4,5,6]

>>> Zip(l,l[1:])
[(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

>>> Zip(l,l[1:])[::2]
[(1, 2), (3, 4), (5, 6)]

>>> [a+b for a,b in Zip(l,l[1:])[::2]]
[3, 7, 11]

>>> ["%d + %d = %d" % (a,b,a+b) for a,b in Zip(l,l[1:])[::2]]
['1 + 2 = 3', '3 + 4 = 7', '5 + 6 = 11']
58
pyanon

Eine einfache Lösung.

 l = [1, 2, 3, 4, 5, 6] ... für i im Bereich (0, len (l), 2): 
 print str (l [i]), '+', str (l [i + 1]), '=', str (l [i] + l [i + 1]) 
55
taskinoor

Obwohl alle Antworten mit Zip korrekt sind, finde ich, dass die Implementierung der Funktionalität selbst zu besser lesbarem Code führt:

def pairwise(it):
    it = iter(it)
    while True:
        yield next(it), next(it)

Der it = iter(it)-Teil stellt sicher, dass it tatsächlich ein Iterator und nicht nur ein Iterator ist. Wenn it bereits ein Iterator ist, ist diese Zeile ein No-Op.

Verwendungszweck:

for a, b in pairwise([0, 1, 2, 3, 4, 5]):
    print(a + b)
34
mic_e

Ich entschuldige mich für die Verspätung. Ich hoffe, das wird noch eleganter.

a = [1,2,3,4,5,6]
Zip(a[::2], a[1::2])

[(1, 2), (3, 4), (5, 6)]
12

Wenn Sie sich für die Leistung interessieren, habe ich einen kleinen Benchmark zum Vergleich der Leistung der Lösungen durchgeführt und eine Funktion aus einem meiner Pakete hinzugefügt: iteration_utilities.grouper

def Johnsyweb(l):
    def pairwise(iterable):
        "s -> (s0, s1), (s2, s3), (s4, s5), ..."
        a = iter(iterable)
        return Zip(a, a)

    for x, y in pairwise(l):
        pass

def Margus(data):
    for i, k in Zip(data[0::2], data[1::2]):
        pass

def pyanon(l):
    list(Zip(l,l[1:]))[::2]

def taskinoor(l):
    for i in range(0, len(l), 2):
        l[i], l[i+1]

def mic_e(it):
    def pairwise(it):
        it = iter(it)
        while True:
            try:
                yield next(it), next(it)
            except StopIteration:
                return

    for a, b in pairwise(it):
        pass

def MSeifert(it):
    for item1, item2 in grouper(it, 2):
        pass

from iteration_utilities import grouper
from simple_benchmark import benchmark_random_list

b = benchmark_random_list(
    [Johnsyweb, Margus, pyanon, taskinoor, mic_e, MSeifert],
    sizes=[2**i for i in range(1, 20)])

b.plot_both(relative_to=MSeifert)

 enter image description here

Windows 10 64-Bit-Anaconda Python 3.6

Wenn Sie also die schnellste Lösung ohne externe Abhängigkeiten suchen, sollten Sie wahrscheinlich die von Johnysweb gegebene Vorgehensweise verwenden (zum Zeitpunkt des Schreibens ist dies die am meisten bewertete und akzeptierte Antwort).

Wenn Sie die zusätzliche Abhängigkeit nicht stört, ist die grouper von iteration_utilities wahrscheinlich etwas schneller.

Zusätzliche Gedanken

Einige Ansätze haben einige Einschränkungen, die hier nicht besprochen wurden.

Zum Beispiel funktionieren einige Lösungen nur für Sequenzen (d. H. Listen, Zeichenfolgen usw.), z. B. Margus/Pyanon/Taskinoor-Lösungen, die die Indizierung verwenden, während andere Lösungen für beliebige Iterationen (dh Sequenzen und Generatoren, Iteratoren) funktionieren ) wie Johnysweb/mic_e/meine Lösungen.

Dann stellte Johnysweb auch eine Lösung bereit, die für andere Größen als 2 funktioniert, während die anderen Antworten dies nicht tun (in Ordnung, der iteration_utilities.grouper erlaubt es auch, die Anzahl der Elemente auf "Gruppe" zu setzen).

Dann gibt es auch die Frage, was passieren soll, wenn die Anzahl der Elemente ungerade ist. Sollte der Restposten abgewiesen werden? Soll die Liste aufgefüllt werden, damit sie noch größer wird? Soll der restliche Artikel als Single zurückgegeben werden? Die andere Antwort spricht diesen Punkt nicht direkt an. Wenn ich jedoch nichts übersehen habe, verfolgen sie alle den Ansatz, dass der verbleibende Punkt abgewiesen werden sollte (mit Ausnahme der Antwort von taskinoors - dies führt tatsächlich zu einer Ausnahme).

Mit grouper können Sie entscheiden, was Sie tun möchten:

>>> from iteration_utilities import grouper

>>> list(grouper([1, 2, 3], 2))  # as single
[(1, 2), (3,)]

>>> list(grouper([1, 2, 3], 2, truncate=True))  # ignored
[(1, 2)]

>>> list(grouper([1, 2, 3], 2, fillvalue=None))  # padded
[(1, 2), (3, None)]
10
MSeifert
for (i, k) in Zip(l[::2], l[1::2]):
    print i, "+", k, "=", i+k

Zip(*iterable) gibt einen Tupel mit dem nächsten Element jedes Iterierbaren zurück.

l[::2] gibt das erste, dritte, fünfte usw. Element der Liste zurück: Der erste Doppelpunkt gibt an, dass das Slice am Anfang beginnt, da keine Zahl dahinter steht. Der zweite Doppelpunkt ist nur erforderlich, wenn Sie einen 'Schritt in der Slice '(in diesem Fall 2).

l[1::2] macht dasselbe, beginnt jedoch im zweiten Element der Listen und gibt das zweite, vierte, sechste usw. Element der original list zurück.

9
alexpinho98

Verwenden Sie die Befehle Zip und iter zusammen:

Ich finde diese Lösung mit iter recht elegant:

it = iter(l)
list(Zip(it, it))
# [(1, 2), (3, 4), (5, 6)]

Was ich in der Python 3 Zip-Dokumentation gefunden habe .

it = iter(l)
print(*(f'{u} + {v} = {u+v}' for u, v in Zip(it, it)), sep='\n')

# 1 + 2 = 3
# 3 + 4 = 7
# 5 + 6 = 11

Um auf N Elemente gleichzeitig zu verallgemeinern:

N = 2
list(Zip(*([iter(l)] * N)))
# [(1, 2), (3, 4), (5, 6)]
7

Für jeden, dem es helfen könnte, ist hier eine Lösung für ein ähnliches Problem, jedoch mit überlappenden Paaren (anstelle von sich gegenseitig ausschließenden Paaren).

Aus der Python itertools Dokumentation :

from itertools import izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)

Oder allgemeiner:

from itertools import izip

def groupwise(iterable, n=2):
    "s -> (s0,s1,...,sn-1), (s1,s2,...,sn), (s2,s3,...,sn+1), ..."
    t = tee(iterable, n)
    for i in range(1, n):
        for j in range(0, i):
            next(t[i], None)
    return izip(*t)
2
Chris Malek

sie können more_itertools package verwenden.

import more_itertools

lst = range(1, 7)
for i, j in more_itertools.chunked(lst, 2):
    print(f'{i} + {j} = {i+j}')
1
Scott Ming

Ich muss eine Liste durch eine Nummer teilen und so fixieren. 

l = [1,2,3,4,5,6]

def divideByN(data, n):
        return [data[i*n : (i+1)*n] for i in range(len(data)//n)]  

>>> print(divideByN(l,2))
[[1, 2], [3, 4], [5, 6]]

>>> print(divideByN(l,3))
[[1, 2, 3], [4, 5, 6]]
1
Ali Katkar

Ein vereinfachter Ansatz:

[(a[i],a[i+1]) for i in range(0,len(a),2)]

dies ist nützlich, wenn Ihr Array ein ist und Sie es paarweise durchlaufen möchten. Um auf Drillingen zu iterieren oder mehr, ändern Sie einfach den Schrittbefehl "Bereich". Beispiel:

[(a[i],a[i+1],a[i+2]) for i in range(0,len(a),3)]

(Sie müssen mit Überschusswerten umgehen, wenn Ihre Arraylänge und der Schritt nicht passen.) 

0
mchrgr2000

Dachte, dass dies ein guter Ort ist, um meine Verallgemeinerung für n> 2 zu teilen, was nur ein Schiebefenster über ein iterables ist:

def sliding_window(iterable, n):
    its = [ itertools.islice(iter, i, None) 
            for i, iter
            in enumerate(itertools.tee(iterable, n)) ]                               

    return itertools.izip(*its)
0
Yuval

Mit der Eingabe können Sie die Daten mit dem Analysetool mypy static überprüfen:

from typing import Iterator, Any, Iterable, TypeVar, Tuple

T_ = TypeVar('T_')
Pairs_Iter = Iterator[Tuple[T_, T_]]

def legs(iterable: Iterator[T_]) -> Pairs_Iter:
    begin = next(iterable)
    for end in iterable:
        yield begin, end
        begin = end
0
Vlad Bezden

Der Titel dieser Frage ist irreführend, Sie scheinen nach aufeinanderfolgenden Paaren zu suchen, aber wenn Sie die Menge aller möglichen Paare durchlaufen möchten, funktioniert dies:

for i,v in enumerate(items[:-1]):
        for u in items[i+1:]:
0
Ofek Ron