Erster Eintrag in for-Schleife in Python überspringen?


186

Wie mache ich in Python so etwas wie:

for car in cars:
   # Skip first and last, do work for rest

4
Ich bin ein Neuling, aber ich habe verwendet for n, i in enumerate(cars): if n!= 0: do something to i. Die Logik ist, dass es jedem Wert einen 'Zähler' hinzufügt, auf den Sie dann zB zielen können if n == some_value. In diesem Beispiel würde es mit jeder Instanz von i etwas tun, mit Ausnahme der ersten.
user1063287

Antworten:


268

Die anderen Antworten funktionieren nur für eine Sequenz.

Um das erste Element zu überspringen:

itercars = iter(cars)
next(itercars)
for car in itercars:
    # do work

Wenn Sie den letzten überspringen möchten, können Sie Folgendes tun:

itercars = iter(cars)
# add 'next(itercars)' here if you also want to skip the first
prev = next(itercars)
for car in itercars:
    # do work on 'prev' not 'car'
    # at end of loop:
    prev = car
# now you can do whatever you want to do to the last one on 'prev'

1
Siehe auch Sven Marnach ‚s Antwort
agf

2
Ich fand, dass cars.pop (0) und cars.pop () gut funktionieren.
Dreamwork801

@ dreamwork801 Meine Antwort und die von Sven, die ich im ersten Kommentar verlinke, funktionieren für alle iterierbaren, sogar unendlichen, da sie keine O (n) -Operation für die Daten erfordern, bevor die Iteration beginnt. Ihr Vorschlag und der von Abhjit funktionieren beide nur für Sequenzen, nicht für iterierbare.
Agf

353

Um das erste Element in Python zu überspringen, können Sie einfach schreiben

for car in cars[1:]:
    # Do What Ever you want

oder um das letzte Element zu überspringen

for car in cars[:-1]:
    # Do What Ever you want

Sie können dieses Konzept für jede Sequenz verwenden.


52
Nicht für alle Iterables , sondern für alle Sequenzen .
Sven Marnach

2
Wie wäre es mit Speichernutzung? Erstellt Slice eine neue Kopie der Subsequenz?
Voyager

@ Voyager Ja, es wird eine neue Kopie erstellt.
Srinivas Reddy Thatiparthy

27

Der beste Weg, um die ersten Elemente zu überspringen, ist:

from itertools import islice
for car in islice(cars, 1, None):
    # do something

islice wird in diesem Fall mit einem Startpunkt von 1 und einem Endpunkt von None aufgerufen, was das Ende des Iterators bedeutet.

Um Elemente vom Ende einer Iterable überspringen zu können, müssen Sie deren Länge kennen (immer möglich für eine Liste, aber nicht unbedingt für alles, was Sie iterieren können). Zum Beispiel überspringt islice (Autos, 1, len (Autos) -1) die ersten und letzten Elemente in der Autoliste.


Schauen Sie sich die (unterschätzte) Antwort von Sven an. Er behandelt das Überspringen einer beliebigen Anzahl von Elementen am Anfang und / oder Ende eines iterierbaren Elements islice, ohne die Länge zu kennen oder mehr Elemente gleichzeitig im Speicher zu speichern, als unbedingt erforderlich.
Agf

Die Antwort von Sven speichert tatsächlich den gesamten Iterator im Speicher - collection.deque wird den Iterator durchlaufen. Versuchen Sie etwas wie collection.deque (xrange (10000000)). Es ist nicht erforderlich, alle Ints im Speicher zu speichern, wenn Sie den ersten Eintrag überspringen möchten ...
Roee Shenberg

2
An isliceist das, was an dequeden gesamten Iterator übergeben wird, und es ist nur die Länge der Anzahl der Elemente, die am Ende übersprungen werden sollen. Es wird nicht der gesamte Iterator gespeichert.
Agf

26

Hier ist eine allgemeinere Generatorfunktion, die eine beliebige Anzahl von Elementen vom Anfang und Ende einer Iterable überspringt:

def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    for x in itertools.islice(it, at_start):
        pass
    queue = collections.deque(itertools.islice(it, at_end))
    for x in it:
        queue.append(x)
        yield queue.popleft()

Anwendungsbeispiel:

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]

Vielleicht möchten Sie einen schnellen Weg für hinzufügen at_end == 0.
Agf

collection.deque (...) durchläuft sofort den Iterator. Dies bedeutet, dass das Überspringen (xrange (10000000), 1) viel Speicherplatz beansprucht, obwohl dies eigentlich nicht der Fall sein sollte.
Roee Shenberg

4
@RoeeShenberg: skip(xrange(10000000), 1)wird verwendet at_end=0, also wird der Parameter deque()sein islice(it, 0), der nur null Elemente von verbraucht it. Dies nimmt nicht viel Speicherplatz in Anspruch.
Sven Marnach

8
for item in do_not_use_list_as_a_name[1:-1]:
    #...do whatever

3
Nicht listals Variablenname verwenden
Abhijit

Das OP möchte nur das erste Element überspringen. warum: -1?
luke14free

6
Es ist nicht wirklich reserviert ; Der Name listkann neu gebunden werden. Deshalb sollten Sie es nicht verwenden , sondern können es nicht verwenden.
Jscs

@ luke14free, die Frage lautet "erstes Element überspringen", aber sein Codekommentar impliziert, dass er wirklich zuerst und zuletzt überspringen möchte.
JerseyMike

@ luke14free das ist, was der Titel sagt, nicht was er in den Code eingegeben hat: "überspringen, wenn zuerst oder zuletzt"
KurzedMetal

3

Basierend auf der Antwort von @SvenMarnach, aber etwas einfacher und ohne Verwendung von Deque

>>> def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    it = itertools.islice(it, at_start, None)
    it, it1 = itertools.tee(it)
    it1 = itertools.islice(it1, at_end, None)
    return (next(it) for _ in it1)

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]
>>> list(skip(range(10), at_start=2, at_end=5))
[2, 3, 4]

Beachten Sie auch, dass dies aufgrund meines timeitErgebnisses geringfügig schneller ist als die Deque-Lösung

>>> iterable=xrange(1000)
>>> stmt1="""
def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    it = itertools.islice(it, at_start, None)
    it, it1 = itertools.tee(it)
    it1 = itertools.islice(it1, at_end, None)
    return (next(it) for _ in it1)
list(skip(iterable,2,2))
    """
>>> stmt2="""
def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    for x in itertools.islice(it, at_start):
        pass
    queue = collections.deque(itertools.islice(it, at_end))
    for x in it:
        queue.append(x)
        yield queue.popleft()
list(skip(iterable,2,2))
        """
>>> timeit.timeit(stmt = stmt1, setup='from __main__ import iterable, skip, itertools', number = 10000)
2.0313770640908047
>>> timeit.timeit(stmt = stmt2, setup='from __main__ import iterable, skip, itertools, collections', number = 10000)
2.9903135454296716

Mit verwenden tee()Sie immer noch eine ganze Liste im Speicher für den Generator, oder? (Ihr it1)
Jabberwockey

3

Beispiel:

mylist=['one'.'two','three'.'four'.'five']
for i in mylist[1:]:
   print(i)

Im Python-Index ab 0 können wir den Slicing-Operator verwenden, um Manipulationen in der Iteration vorzunehmen.

for i in range(1,-1):

2

Nun, Ihre Syntax ist zunächst nicht wirklich Python.

Iterationen in Python sind über den Inhalt von Containern (technisch gesehen über Iteratoren) mit einer Syntax for item in container. In diesem Fall ist der Container die carsListe, aber Sie möchten das erste und das letzte Element überspringen. Das bedeutet, dass cars[1:-1]Python-Listen auf Null basieren, negative Zahlen vom Ende an zählen und die :Syntax aufteilen.

Also du möchtest

for c in cars[1:-1]:
    do something with c

4
Dies funktioniert nicht mit einem Iterable (z. B. einem Generator), sondern nur mit einer Sequenz.
Roee Shenberg

2

Eine alternative Methode:

for idx, car in enumerate(cars):
    # Skip first line.
    if not idx:
        continue
    # Skip last line.
    if idx + 1 == len(cars):
        continue
    # Real code here.
    print car

2

Hier ist meine bevorzugte Wahl. Es erfordert nicht viel Hinzufügen zur Schleife und verwendet nur eingebaute Werkzeuge.

Gehe von:

for item in my_items:
  do_something(item)

zu:

for i, item in enumerate(my_items):
  if i == 0:
    continue
  do_something(item)

1

Wenn carses sich um eine Sequenz handelt, können Sie dies einfach tun

for car in cars[1:-1]:
    pass

1

Das more_itertoolsProjekt erstreckt sich itertools.isliceauf negative Indizes.

Beispiel

import more_itertools as mit

iterable = 'ABCDEFGH'
list(mit.islice_extended(iterable, 1, -1))
# Out: ['B', 'C', 'D', 'E', 'F', 'G']

Daher können Sie es elegant auf Slice-Elemente zwischen dem ersten und dem letzten Element einer Iterable anwenden:

for car in mit.islice_extended(cars, 1, -1):
    # do something

0

Ich mache es so, obwohl es wie ein Hack aussieht, funktioniert es jedes Mal:

ls_of_things = ['apple', 'car', 'truck', 'bike', 'banana']
first = 0
last = len(ls_of_things)
for items in ls_of_things:
    if first == 0
        first = first + 1
        pass
    elif first == last - 1:
        break
    else:
        do_stuff
        first = first + 1
        pass
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.