Extraia elementos da lista em posições ímpares


100

Então, eu quero criar uma lista que é uma sublista de alguma lista existente.

Por exemplo,

L = [1, 2, 3, 4, 5, 6, 7], Desejo criar uma sublista lique licontenha todos os elementos em Lposições ímpares.

Embora eu possa fazer isso

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

Mas eu quero saber se existe outra maneira de fazer o mesmo com eficiência e em menos número de etapas.


@WaleedKhan: Por que ele precisa listar as compreensões em uma pergunta?
Tamara Wijsman

1
@TomWijsman: Compreensões de listas . ETA: Desconsidere isso: eu procurei e descobri esta sua resposta que indica que você está brincando. Coloque uma carinha sorridente na próxima vez!
David Robinson,

2
@DavidRobinson: Mas outras pessoas podem dizer isso, pode não estar claro para OP o que ele quer dizer com duas palavras ambíguas. Basta apontar aqui e ali com alguns comentários, para que as pessoas se preparem e escrevam melhor conteúdo; e para evitar deixar o OP ou visitantes sem noção ... :)
Tamara Wijsman

Respostas:


229

Solução

Sim você pode:

l = L[1::2]

E isso é tudo. O resultado conterá os elementos colocados nas seguintes posições ( 0com base em, portanto, o primeiro elemento está na posição 0, o segundo em 1etc.):

1, 3, 5

então o resultado (números reais) será:

2, 4, 6

Explicação

O [1::2]no final é apenas uma notação para divisão de lista. Normalmente tem o seguinte formato:

some_list[start:stop:step]

Se omitimos start, o default ( 0) seria usado. Portanto, o primeiro elemento (na posição 0, porque os índices são 0baseados) seria selecionado. Neste caso, o segundo elemento será selecionado.

Como o segundo elemento foi omitido, o padrão está sendo usado (o final da lista). Portanto, a lista está sendo iterada do segundo elemento até o final .

Também fornecemos o terceiro argumento ( step), que é 2. O que significa que um elemento será selecionado, o próximo será ignorado e assim por diante ...

Então, para resumir, neste caso [1::2]significa:

  1. pegue o segundo elemento (que, a propósito, é um elemento estranho, se você julgar pelo índice),
  2. pular um elemento (porque temos step=2, então estamos pulando um, ao contrário do step=1que é padrão),
  3. pegue o próximo elemento,
  4. Repita as etapas 2.-3. até que o fim da lista seja alcançado,

EDIT : @PreetKukreti forneceu um link para outra explicação sobre a notação de fatiamento de lista do Python. Veja aqui: Explique a notação de fatia do Python

Extras - substituindo contador com enumerate()

Em seu código, você cria e aumenta explicitamente o contador. Em Python, isso não é necessário, pois você pode enumerar por meio de alguns iteráveis ​​usando enumerate():

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

O acima tem exatamente a mesma finalidade que o código que você estava usando:

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

Mais sobre emulação de forloops com contador em Python: Acessando o índice em Python 'for' loops


@TomWijsman veja esta questão para entender a sintaxe de
divisão do

A pergunta pede posições estranhas. Isso dá posições uniformes (0,2,4,6); parece que o OP deseja índices (1,3,5), que seriam dados por [1,2,3,4,5,6,7][1::2].
Marcin,

@Marcin: Sim, na verdade cheguei à mesma conclusão (ver correção). Isso saiu depois que eu li o código do OP cuidadosamente. O problema resultou em uma base diferente para indexação (para mim, elemento " ímpar " significava o primeiro elemento, para OP aparentemente era o segundo , portanto indexado em 1).
Tadeck de

1
@TomWijsman: Sinto muito, não percebi o que você mudou. Na verdade, há um link, mas ele leva ao projeto Numarray, não ao listfatiamento do Python . É um pouco diferente, especialmente porque a listfatia de não mantém referência à lista original (em Numarray você precisa chamar explicitamente .copy()para ter algo que não faça referência ao array original). Mas é bom ter algo que pode ser melhor para alguns leitores. Você se importaria de colocar este link no comentário, para que eu possa votar a favor e ele aparecerá logo abaixo da resposta?
Tadeck de

@Tadeck "Índices com números ímpares" muito naturalmente significa índices que são números ímpares.
Marcin,

12

Para as posições ímpares , você provavelmente deseja:

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

3

Eu gosto de compreensões de lista por causa de sua sintaxe Math (Set). Então, que tal isso:

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]

Basicamente, se você enumerar em uma lista, obterá o índice xe o valor y. O que estou fazendo aqui é colocar o valor yna lista de saída (par ou ímpar) e usar o índice xpara descobrir se esse ponto é ímpar ( x%2 != 0).


1
Não deveria ser enumerar (L) em vez de enumerar (itens)?
ab123

0

Você pode fazer uso do operador AND bit a bit &. Vamos ver abaixo:

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

O operador AND bit a bit é usado com 1, e o motivo pelo qual funciona é que, o número ímpar quando escrito em binário deve ter seu primeiro dígito como 1. Vamos verificar

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

A operação AND com 1 retornará apenas 1 (1 em binário também terá o último dígito 1), se o valor for ímpar.

Verifique a página do Python Bitwise Operator para mais informações.

PS: Você pode usar esse método taticamente se quiser selecionar colunas ímpares e pares em um dataframe. Digamos que as coordenadas xey dos pontos-chave faciais sejam dadas como colunas x1, y1, x2, etc ... Para normalizar as coordenadas xey com os valores de largura e altura de cada imagem, você pode simplesmente executar

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

Isso não está exatamente relacionado à questão, mas para cientistas de dados e engenheiros de visão computacional, esse método pode ser útil.

Felicidades!


-1

lista_ = lista (intervalo (9)) impressão (lista_ [1 :: 2])


responda com uma breve explicação e coloque alguns blocos de código devidamente formatados. Obrigado
venkata Krishnan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.