Extrahieren Sie Listenelemente an ungeraden Positionen

100

Ich möchte also eine Liste erstellen, die eine Unterliste einer vorhandenen Liste ist.

Beispielsweise,

L = [1, 2, 3, 4, 5, 6, 7]Ich möchte eine Unterliste erstellen li, lidie alle Elemente Lan ungeraden Positionen enthält.

Während ich es schaffen kann

L = [1, 2, 3, 4, 5, 6, 7]
li = []
count = 0
for i in L:
    if count % 2 == 1:
        li.append(i)
    count += 1

Aber ich möchte wissen, ob es einen anderen Weg gibt, dasselbe effizient und in weniger Schritten zu tun.

veepsk
quelle
@WaleedKhan: Warum muss er Verständnis in einer Frage auflisten?
Tamara Wijsman
1
@ TomWijsman: Listenverständnisse . ETA: Ignorieren Sie das: Ich habe mich umgesehen und Ihre Antwort entdeckt , die darauf hinweist, dass Sie Witze machen. Setzen Sie beim nächsten Mal ein Smiley-Gesicht!
David Robinson
2
@ DavidRobinson: Aber können andere Leute das sagen, es ist möglicherweise nicht klar, was er mit zwei mehrdeutigen Worten meint. Nur hier und da mit ein paar Kommentaren stechen, damit die Leute sich darauf vorbereiten und bessere Inhalte schreiben; und um zu vermeiden, das OP oder Besucher ahnungslos zu verlassen ... :)
Tamara Wijsman

Antworten:

229

Lösung

Ja, du kannst:

l = L[1::2]

Und das ist alles. Das Ergebnis enthält die Elemente, die an den folgenden Positionen platziert sind ( 0-basiert, sodass sich das erste Element an der Position befindet 0, das zweite an der Position 1usw.):

1, 3, 5

Das Ergebnis (tatsächliche Zahlen) lautet also:

2, 4, 6

Erläuterung

Das [1::2]am Ende ist nur eine Notation für das Aufteilen von Listen. Normalerweise ist es in der folgenden Form:

some_list[start:stop:step]

Wenn wir dies weglassen start, wird default ( 0) verwendet. Daher würde das erste Element (an Position 0, da die Indizes 0basieren) ausgewählt. In diesem Fall wird das zweite Element ausgewählt.

Da das zweite Element weggelassen wird, wird der Standard verwendet (das Ende der Liste). Die Liste wird also vom zweiten Element bis zum Ende wiederholt .

Wir haben auch das dritte Argument ( step) angegeben 2. Das heißt, ein Element wird ausgewählt, das nächste wird übersprungen und so weiter ...

Zusammenfassend [1::2]bedeutet dies in diesem Fall :

  1. Nehmen Sie das zweite Element (das übrigens ein ungerades Element ist, wenn Sie nach dem Index urteilen).
  2. ein Element überspringen (weil wir haben step=2, also überspringen wir eines, im Gegensatz zu step=1dem , was standardmäßig ist),
  3. nimm das nächste Element,
  4. Wiederholen Sie die Schritte 2.-3. bis das Ende der Liste erreicht ist,

EDIT : @PreetKukreti gab einen Link für eine andere Erklärung auf Python Liste Slicing - Notation. Siehe hier: Erklären Sie Pythons Slice-Notation

Extras - Zähler durch ersetzen enumerate()

In Ihrem Code erstellen und erhöhen Sie den Zähler explizit. In Python ist dies nicht erforderlich, da Sie einige iterable mithilfe von enumerate():

for count, i in enumerate(L):
    if count % 2 == 1:
        l.append(i)

Das Obige dient genau dem gleichen Zweck wie der von Ihnen verwendete Code:

count = 0
for i in L:
    if count % 2 == 1:
        l.append(i)
    count += 1

Weitere Informationen zum Emulieren von forSchleifen mit Zähler in Python: Zugriff auf den Index in Python 'for'-Schleifen

Tadeck
quelle
@ TomWijsman schauen Sie sich diese Frage an, um die Python-Slicing-Syntax zu verstehen
Preet Kukreti
Die Frage fragt nach ungeraden Positionen. Dies ergibt gleichmäßige Positionen (0,2,4,6); es klingt so, als ob OP Indizes will (1,3,5), die von gegeben wären [1,2,3,4,5,6,7][1::2].
Marcin
@Marcin: Ja, ich bin tatsächlich zu dem gleichen Schluss gekommen (siehe Korrektur). Dies kam heraus, nachdem ich den Code des OP sorgfältig gelesen hatte. Das Problem ergab sich aus einer anderen Basis für die Indizierung (für mich bedeutete " ungerades " Element das erste Element, für OP war es anscheinend das zweite , also indiziert bei 1).
Tadeck
1
@ TomWijsman: Es tut mir leid, ich habe nicht bemerkt, was Sie geändert haben. Es gibt zwar einen Link, der jedoch zum Numarray-Projekt führt, nicht zu Pythons listSlicing. Es unterscheidet sich ein wenig, insbesondere weil das listSlice des 's nicht auf die ursprüngliche Liste verweist (in Numarray müssen Sie explizit aufrufen .copy(), um etwas zu haben, das nicht auf das ursprüngliche Array verweist). Aber es ist schön, etwas zu haben, das für manche Leser besser sein könnte. Würde es Ihnen etwas ausmachen, diesen Link in den Kommentar aufzunehmen, damit ich ihn positiv bewerten kann und er direkt unter der Antwort angezeigt wird?
Tadeck
@Tadeck "Ungeradzahlige Indizes" bedeutet ganz natürlich Indizes, die ungerade Zahlen sind.
Marcin
12

Für die ungeraden Positionen möchten Sie wahrscheinlich:

>>>> list_ = list(range(10))
>>>> print list_[1::2]
[1, 3, 5, 7, 9]
>>>>
Dstromberg
quelle
3

Ich mag Listenverständnisse wegen ihrer Math (Set) -Syntax. Wie wäre es damit:

L = [1, 2, 3, 4, 5, 6, 7]
odd_numbers = [y for x,y in enumerate(L) if x%2 != 0]
even_numbers = [y for x,y in enumerate(L) if x%2 == 0]

Wenn Sie über eine Liste aufzählen, erhalten Sie grundsätzlich den Index xund den Wert y. Was ich hier mache, ist, den Wert yin die Ausgabeliste (gerade oder ungerade) zu setzen und anhand des Index xherauszufinden, ob dieser Punkt ungerade ist ( x%2 != 0).

Peterb
quelle
1
Sollte es nicht Aufzählung (L) statt Aufzählung (Elemente) sein?
ab123
0

Sie können den bitweisen AND-Operator verwenden &. Mal sehen:

x = [1, 2, 3, 4, 5, 6, 7]
y = [i for i in x if i&1]
>>> 
[1, 3, 5, 7]

Der bitweise AND-Operator wird mit 1 verwendet, und der Grund dafür ist, dass eine ungerade Zahl, wenn sie in Binärform geschrieben ist, ihre erste Ziffer als 1 haben muss

23 = 1 * (2**4) + 0 * (2**3) + 1 * (2**2) + 1 * (2**1) + 1 * (2**0) = 10111
14 = 1 * (2**3) + 1 * (2**2) + 1 * (2**1) + 0 * (2**0) = 1110

Eine UND-Verknüpfung mit 1 gibt nur 1 zurück (1 in Binär hat auch die letzte Ziffer 1), wenn der Wert ungerade ist.

Weitere Informationen finden Sie auf der Seite Python Bitwise Operator .

PS: Sie können diese Methode taktisch verwenden, wenn Sie ungerade und gerade Spalten in einem Datenrahmen auswählen möchten. Angenommen, die x- und y-Koordinaten der Gesichtsschlüsselpunkte werden als Spalten x1, y1, x2 usw. angegeben. Um die x- und y-Koordinaten mit den Breiten- und Höhenwerten jedes Bildes zu normalisieren, können Sie einfach eine Ausführung durchführen

for i in range(df.shape[1]):
    if i&1:
        df.iloc[:, i] /= heights
    else:
        df.iloc[:, i] /= widths

Dies hängt nicht genau mit der Frage zusammen, aber für Datenwissenschaftler und Computer Vision-Ingenieure könnte diese Methode nützlich sein.

Prost!

Suvo
quelle
-1

list_ = list (range (9)) print (list_ [1 :: 2])

user11855765
quelle
Bitte antworten Sie mit einer kurzen Erklärung und setzen Sie einige Codeblöcke richtig formatiert. Danke
venkata krishnan