As funções sort e sorted são tradicionalmente empregadas para ordenar (classificar) listas. A operação de ordenação possibilita a identificação fácil de elementos de uma lista através de suas posições na ordem encontrada. Porém, saber Python envolve desafiar os comandos tradicionais e buscar soluções mais criativas e, de preferência, computacionalmente mais eficazes. Esse é o objetivo desse post: encontrar o segundo menor item de uma Python lista com um método alternativo ao uso da função sort.
NumPy
Para acompanhar esse post na prática, é preciso possuir a biblioteca NumPy instalada. Para fazer a instalação com pip:
pip install numpy
Para instalação através do conda:
conda install anaconda::numpy
Conversão de uma Python lista para um array NumPy
É perfeitamente possível encontrar o segundo menor elemento de uma lista sem usar a função sort. Primeiro, convertemos a lista de interesse para um NumPy array. Isso é feito com a função np.array.
import numpy as np
# Converte uma lista em um NumPy array
minha_lista = [21, 4, 0, 2, 9, 22, 23, 6, 8, 5, 3, 12, 7]
meu_array = np.array(minha_lista)
O segundo menor item de uma Python lista
Depois usamos uma função muito interessante do NumPy: np.partition.
A função np.partition é uma ferramenta poderosa do NumPy para organizar parcialmente um array. Ela permite reorganizar os itens de um array a partir da definição de um índice k de interesse. Esse índice é a posição em que estamos interessados. No nosso exemplo, o segundo menor item de uma lista tem índice igual a 1.
A função np.partition usa o índice k para criar uma cópia do array com seus elementos reorganizados. Nesse novo array, o elemento na k-ésima posição está posicionado onde o valor estaria em um array ordenado. No array particionado, todos os elementos antes do k-ésimo elemento são menores ou iguais a esse elemento, e todos os elementos após o k-ésimo elemento são maiores ou iguais a esse elemento. A ordem dos elementos nas duas partições é indefinida.
meu_array_particionado = np.partition(meu_array, 1)
print(meu_array_particionado)
No trecho de código acima, na linha 1, o valor 1 corresponde ao índice do segundo menor elemento. O novo array criado pela função np.partition para nosso exemplo é mostrado abaixo. O array que foi usado no exemplo foi o mesmo que mostramos na sessão acima.
[ 0 2 21 4 9 22 23 6 8 5 3 12 7]
Outros exemplos
Evidentemente, a função np.partition não se restringe a identificar apenas o segundo menor elemento de uma lista. No trecho abaixo demonstramos como essa função pode ser usada para identificar, por exemplo, o quinto, o terceiro e o sétimo menor item de uma Python lista.
import numpy as np
minha_lista = [100, 77, 46, 50, 95, 13, 85, 70, 20, 10, 25, 35, 5, 7, 23, 35]
meu_array = np.array(minha_lista) # converte lista em array
# particiona a lista a partir do 5o elemento
meu_array_particionado_quinto_menor_item = np.partition(meu_array, 4)
# particiona a lista a partir do 3o elemento
meu_array_particionado_terceiro_menor_item = np.partition(meu_array, 2)
# particiona a lista a partir do 7o elemento
meu_array_particionado_setimo_menor_item = np.partition(meu_array, 6)
Abaixo mostramos os três novos arrays criados. Perceba que as sequências tanto à direita quanto à esquerda do elemento de índice k são desordenadas. O elemento de índice k apenas separa elementos de menor valor a sua esquerda e de maior valor à direita.
# array original
[100 77 46 50 95 13 85 70 20 10 25 35 5 7 23 35]
# lista particionada no 5o elemento
[ 5 7 10 13 20 23 25 35 50 46 35 70 77 85 95 100]
# lista particionada no 3o elemento
[ 5 7 10 50 95 13 85 70 20 46 25 35 100 77 23 35]
# lista particionada no 7o elemento
[ 7 13 10 20 23 5 25 35 50 46 35 70 77 85 95 100]