Estrai gli elementi della lista in posizioni dispari


100

Quindi voglio creare un elenco che sia un sottoelenco di un elenco esistente.

Per esempio,

L = [1, 2, 3, 4, 5, 6, 7], Voglio creare una sottolista litale che licontenga tutti gli elementi in Lposizioni dispari.

Mentre posso farlo da

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

Ma voglio sapere se esiste un altro modo per fare lo stesso in modo efficiente e con un numero inferiore di passaggi.


@WaleedKhan: Perché ha bisogno di elencare le comprensioni in una domanda?
Tamara Wijsman,

1
@TomWijsman: Elenca comprensioni . ETA: Ignoralo: ho cercato in giro e ho scoperto questa tua risposta che indica che stai scherzando. Metti una faccina sorridente la prossima volta!
David Robinson

2
@DavidRobinson: Ma gli altri possono dirlo, potrebbe non essere chiaro OP cosa intende con due parole ambigue. Solo pugnalando qua e là con alcuni commenti, così le persone si preparano e scrivono contenuti migliori; e per evitare di lasciare l'OP o i visitatori all'oscuro ... :)
Tamara Wijsman

Risposte:


229

Soluzione

Si, puoi:

l = L[1::2]

E questo è tutto. Il risultato conterrà gli elementi posizionati nelle seguenti posizioni ( 0-based, quindi il primo elemento è in posizione 0, il secondo in 1ecc.):

1, 3, 5

quindi il risultato (numeri effettivi) sarà:

2, 4, 6

Spiegazione

Alla [1::2]fine è solo una notazione per l'affettamento della lista. Di solito è nella seguente forma:

some_list[start:stop:step]

Se omettessimo start, 0verrebbe usato il default ( ). Quindi il primo elemento (in posizione 0, perché gli indici sono 0basati su -based) verrebbe selezionato. In questo caso verrà selezionato il secondo elemento.

Poiché il secondo elemento viene omesso, viene utilizzato il valore predefinito (la fine dell'elenco). Quindi l'elenco viene iterato dal secondo elemento alla fine .

Abbiamo anche fornito il terzo argomento ( step) che è 2. Ciò significa che verrà selezionato un elemento, il successivo verrà ignorato e così via ...

Quindi, per riassumere, in questo caso [1::2]significa:

  1. prendi il secondo elemento (che, a proposito, è un elemento strano, se giudichi dall'indice),
  2. saltare un elemento (perché ne abbiamo step=2, quindi ne stiamo saltando uno, al contrario di quello step=1predefinito),
  3. prendi l'elemento successivo,
  4. Ripeti i passaggi 2.-3. fino alla fine della lista,

EDIT : @PreetKukreti ha fornito un collegamento per un'altra spiegazione sulla notazione di suddivisione dell'elenco di Python. Vedi qui: Spiega la notazione slice di Python

Extra: sostituzione del contatore con enumerate()

Nel tuo codice crei e aumenti esplicitamente il contatore. In Python questo non è necessario, poiché puoi enumerare tramite alcuni iterabili usando enumerate():

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

Quanto sopra ha esattamente lo stesso scopo del codice che stavi usando:

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

Ulteriori informazioni sull'emulazione di forloop con counter in Python: Accesso all'indice in Python "for" loop


@TomWijsman guarda questa domanda per capire la sintassi del taglio di python
Preet Kukreti

La domanda richiede posizioni dispari. Questo dà anche posizioni (0,2,4,6); sembra che OP voglia gli indici (1,3,5), che sarebbero dati da [1,2,3,4,5,6,7][1::2].
Marcin

@ Marcin: Sì, in realtà sono uscito con la stessa conclusione (vedi correzione). Questo è venuto fuori dopo aver letto attentamente il codice dell'OP. Il problema è risultato su una base diversa per l'indicizzazione (per me l' elemento " dispari " significava il primo elemento, per OP apparentemente era il secondo , quindi indicizzato a 1).
Tadeck

1
@ TomWijsman: mi dispiace, non ho notato cosa hai cambiato. In effetti, c'è un collegamento, ma porta al progetto Numarray, non allo listslicing di Python . È un po 'diverso, soprattutto perché lo listslice di non mantiene il riferimento alla lista originale (in Numarray devi chiamare esplicitamente .copy()per avere qualcosa che non fa riferimento all'array originale). Ma è bello avere qualcosa che potrebbe essere migliore per alcuni lettori. Ti dispiacerebbe postare questo link nel commento, così posso votare a favore e apparirà appena sotto la risposta?
Tadeck

@Tadeck "Indici numerati dispari" significa abbastanza naturalmente indici che sono numeri dispari.
Marcin

12

Per le posizioni dispari , probabilmente vorrai:

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

3

Mi piacciono le liste di comprensione a causa della loro sintassi matematica (Set). Allora che ne dici di questo:

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]

Fondamentalmente, se enumerate su un elenco, otterrete l'indice xe il valore y. Quello che sto facendo qui è inserire il valore ynell'elenco di output (pari o dispari) e utilizzare l'indice xper scoprire se quel punto è dispari ( x%2 != 0).


1
Non dovrebbe essere enumerate (L) invece di enumerate (items)?
ab123

0

È possibile utilizzare l'operatore AND bit per bit &. Vediamo di seguito:

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

L'operatore AND bit per bit viene utilizzato con 1 e il motivo per cui funziona perché un numero dispari quando scritto in binario deve avere la prima cifra come 1. Controlliamo

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

L'operazione AND con 1 restituirà solo 1 (1 in binario avrà anche l'ultima cifra 1), se e solo se il valore è dispari.

Controlla la pagina Python Bitwise Operator per ulteriori informazioni.

PS: puoi usare tatticamente questo metodo se desideri selezionare colonne pari e dispari in un dataframe. Supponiamo che le coordinate xey dei punti chiave facciali siano date come colonne x1, y1, x2, ecc ... Per normalizzare le coordinate xey con i valori di larghezza e altezza di ciascuna immagine puoi semplicemente eseguire

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

Questo non è esattamente correlato alla domanda, ma per i data scientist e gli ingegneri di computer vision questo metodo potrebbe essere utile.

Saluti!


-1

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


si prega di rispondere con una breve spiegazione e di inserire alcuni blocchi di codice correttamente formattati. Grazie
venkata krishnan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.