Manipulando listas com #Python. (#dev)
Overview
Olá, entusiastas da programação! Hoje, vamos mergulhar no mundo do Python para explorar algumas técnicas poderosas de manipulação e iteração de listas. Desde mesclar listas e acessar elementos de maneira criativa, até iterar com padrões específicos, este post está recheado de dicas úteis. Prepare seu ambiente de desenvolvimento e vamos codificar juntos!
Neste post, mostro um pouco das funcionalidades para acessar elementos, mesclar listas, mostrar listas no sentido inverso, iterar sobre a lista de 2 em 2 elementos, etc.
Primeiro, para todos os exemplos, vou usar as seguintes listas:
foo = ["00 bacon", "01 foo", "02 bar", "03 lettuce", "04 pancakes", "05 waffles"]
bar = [0, 1, 1, 2, 3, 5]
Mesclando listas
É possível mesclar listas da mesma forma que você passa *args para funções…
foobar = [*foo, *bar]
['00 bacon',
'01 foo',
'02 bar',
'03 lettuce',
'04 pancakes',
'05 waffles',
0,
1,
1,
2,
3,
5]
Acessando o elemento n da lista
Este é o comportamento normal de qualquer lista/array que conhecemos. Não quis deixar o básico de fora…
foo[0]
'00 bacon'
Acessando o último elemento da lista
Sem funcionalidades como linq, geralmente você tem que pegar o tamanho da lista e subtrair 1 para saber o índice do último item da lista. No Python é só usar -1 como índice.
foo[-1]
'05 waffles'
Acessando o penúltimo elemento da lista
Esta lógica não é apenas para o último item. Você pode utilizar números negativos para percorrer a lista ao contrário (não é a melhor opção para isso, mas é uma das possibilidades).
foo[-2]
'04 pancakes'
Pulando n itens da lista
É possível utilizar as listas “pulando” ou ignorando os n primeiros itens dela.
foo[1:]
['01 foo', '02 bar', '03 lettuce', '04 pancakes', '05 waffles']
Pegando n itens da lista
De forma similar, você pode apenas pegar um número limitado de itens da lista, ao invés de pegar a lista toda de uma vez.
foo[:3]
['00 bacon', '01 foo', '02 bar']
Pegando uma “fatia” da lista
É possível combinar a lógica de “pular n itens” e “pegar n itens”, mas essa abordagem tem um detalhe importante.
foo[2:4]
['02 bar', '03 lettuce']
O detalhe aqui é o seguinte, primeiro você vai pegar os 4 primeiros itens e depois vai ignorar os 2 primeiros. É um pouco contraintuitivo de ler, já que o “comando” para pular os dois primeiros itens vem primeiro, mas a ideia é essa: Primeiro você separa os itens que vai utilizar, depois vc “aplica” o filtro de ignorar itens.
Neste caso, para o comando de “pegar n itens” você não precisa se preocupar com o tamanho da lista. O Python vai te devolver o número de itens que você pediu até chegar ao final da lista. Se ele não possuir a quantidade de elementos que você pediu, paciência. Seu resultado será uma lista menor. Veja este segundo exemplo:
foo[2:940000]
['02 bar', '03 lettuce', '04 pancakes', '05 waffles']
Veja que peguei os 940.000 itens e ignorei os 2 primeiros. Minha lista s;o tinha 6 elementos, então o meu resultado contempla apenas os 4 últimos elementos.
Iterando pela lista, 2 elementos por vez
Geralmente, quando fazemos um for em uma lista, ele passa por todos os elementos, mas você pode querer que ele passe por 1 e pule 1.
foo[::2]
['00 bacon', '02 bar', '04 pancakes']
Sim, tem outro : no processo. Ele sempre existiu em todos os outros exemplos, mas quando ele é omitido, o padrão é 1.
Invertendo a lista
Você pode usar a abordagem anterior, combinada com os outros exemplos deste post para inverter a ordem da lista.
foo[::-1]
['05 waffles', '04 pancakes', '03 lettuce', '02 bar', '01 foo', '00 bacon']
Que tal inverter a lista, pegando um elemento e ignorando o outro?
foo[::-2]
['05 waffles', '03 lettuce', '01 foo']
Outra forma de inverter uma lista é utilizando a função reversed…
reversed(foo)
<list_reverseiterator at 0x5cef000>
Porém ela retorna um generator e não a lista invertida. Utilizando este método, para pegar a lista invertida, você precisaria converte-la:
list(reversed(foo))
['05 waffles', '04 pancakes', '03 lettuce', '02 bar', '01 foo', '00 bacon']
Então, quando usar foo[::-1] e quando usar reversed(foo)? Bom, depende do que você precisar, do tamanho das listas, dos requerimentos de desempenho, etc.
Iterando por duas listas ao mesmo tempo
É possível fazer um for e passar por duas listas ao mesmo tempo.
for f, b in zip(foo, bar):
print(f"This is an element of foo: {f}")
print(f"This is an element of bar: {b}")
This is an element of foo: 00 bacon
This is an element of bar: 0
This is an element of foo: 01 foo
This is an element of bar: 1
This is an element of foo: 02 bar
This is an element of bar: 1
This is an element of foo: 03 lettuce
This is an element of bar: 2
This is an element of foo: 04 pancakes
This is an element of bar: 3
This is an element of foo: 05 waffles
This is an element of bar: 5
Se precisar, consegue também incluir um índice nesta operação:
for i, (f, b) in enumerate(zip(foo, bar)):
print(f"[{i}] This is an element of foo: {f}")
print(f"[{i}] This is an element of bar: {b}")
[0] This is an element of foo: 00 bacon
[0] This is an element of bar: 0
[1] This is an element of foo: 01 foo
[1] This is an element of bar: 1
[2] This is an element of foo: 02 bar
[2] This is an element of bar: 1
[3] This is an element of foo: 03 lettuce
[3] This is an element of bar: 2
[4] This is an element of foo: 04 pancakes
[4] This is an element of bar: 3
[5] This is an element of foo: 05 waffles
[5] This is an element of bar: 5
Existe um detalhe importante! Se as listas forem de tamanhos diferentes, a iteração será feita pegando o número de elementos das menor lista.
bar2 = [42, *bar]
for i, (f, b) in enumerate(zip(foo, bar2)): # Attention! if the lists have different sizes, will iterate the number of elements of the first list.
print(f"[{i}] This is an element of foo: {f}")
print(f"[{i}] This is an element of bar: {b}")
print("Note that 5 (last element of bar2) was not included in the for")
[0] This is an element of foo: 00 bacon
[0] This is an element of bar: 42
[1] This is an element of foo: 01 foo
[1] This is an element of bar: 0
[2] This is an element of foo: 02 bar
[2] This is an element of bar: 1
[3] This is an element of foo: 03 lettuce
[3] This is an element of bar: 1
[4] This is an element of foo: 04 pancakes
[4] This is an element of bar: 2
[5] This is an element of foo: 05 waffles
[5] This is an element of bar: 3
Note that 5 (last element of bar2) was not included in the for
No exemplo acima, a lista foo tem um elemento a menos que a lista bar2 e isso fez com que o último elemento da lista bar2 fosse ignorado.
Realizando operações em cada item da lista
Uma forma rápida e limpa de multiplicarmos todos os elementos da lista bar por 2.
x = [n*2 for n in bar]
print(bar)
print(x)
[0, 1, 1, 2, 3, 5]
[0, 2, 2, 4, 6, 10]
Utilizando all e any
All e any são funções que não manipulam listas, mas são muito úteis e resolvi incluir aqui
x = [n % 2 == 0 for n in bar]
print(bar)
print(x)
print(f"All elements of bar are even numbers? - {all(x)}")
print(f"Any elements of bar is an even number? - {any(x)}")
Acimn eu criar a lista x, que contem apenas true ou false, indicando se o elemento correspondente na lista bar é ou não par.
Quando chamo a função all, ela retorna true se todos os elementos de x forem true. De forma similar, any vai retornar true se pelo menos 1 item da lista x for true.
É isso. Espero ter ajudado!