Problema
Dada uma lista de elementos, que pode incluir números inteiros, floats e outros tipos de dados, desenvolva uma função para retornar o segundo maior número presente na lista. Trate situações como listas vazias, listas com um único elemento ou contendo itens não numéricos. Inclua testes unitários para validar a solução.
Observações
- Elimine qualquer elemento que não seja do tipo int ou float antes do processamento.
- Lide com duplicatas: se o valor máximo ocorrer múltiplas vezes, o segundo maior deve ser o próximo valor distinto inferior ao máximo.
- Métodos integrados como
list.sort(reverse=True)eheapq.nlargestmantêm a contagem de elementos, o que pode incluir duplicatas.
Função de Filtragem de Dados
Criamos uma função para remover elementos inválidos da lista original.
def filtrar_elementos_numericos(entrada):
"""Retorna uma nova lista contendo apenas inteiros ou floats."""
resultado = []
for item in entrada:
if isinstance(item, (int, float)):
resultado.append(item)
return resultado
Método 1: Busca Direta
Este método encontra o segundo maior valor sem remover duplicatas previamente.
import sys
def obter_segundo_maior_metodo1(dados):
lista_filtrada = filtrar_elementos_numericos(dados)
tamanho = len(lista_filtrada)
if tamanho == 0:
print("A lista não contém elementos numéricos.")
return None
if tamanho == 1:
print("Há apenas um número na lista:", lista_filtrada[0])
return None
if tamanho > sys.maxsize:
print("A lista é excessivamente grande.")
return None
maximo = max(lista_filtrada)
minimo = min(lista_filtrada)
if maximo == minimo:
return None # Todos os números são iguais
segundo_max = minimo
for numero in lista_filtrada:
if numero < maximo and numero > segundo_max:
segundo_max = numero
return segundo_max
Testes Unitários
Implementamos uma suíte de testes para validar a função.
import unittest
class TesteObterSegundoMaior(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("Iniciando execução dos testes...")
@classmethod
def tearDownClass(cls):
print("Testes finalizados.")
def test_lista_vazia(self):
self.assertIsNone(obter_segundo_maior_metodo1([]))
def test_lista_com_um_elemento(self):
self.assertIsNone(obter_segundo_maior_metodo1([15]))
def test_apenas_dados_invalidos(self):
self.assertIsNone(obter_segundo_maior_metodo1([None, "texto", [1, 2]]))
def test_um_numero_apos_filtragem(self):
self.assertIsNone(obter_segundo_maior_metodo1([None, 7, "abc"]))
def test_maximo_com_duplicatas(self):
dados = [45, None, 22, "xyz", 10, 8, 50, 5, 45, 6, 50, 12, 30, '40', 50]
self.assertEqual(obter_segundo_maior_metodo1(dados), 45)
if __name__ == '__main__':
unittest.main()
Método 2: Eliminação do Máximo
Nesta abordagem, removemos todas as ocorrências do maior elemento e buscamos o novo máximo.
def obter_segundo_maior_metodo2(dados):
lista_filtrada = filtrar_elementos_numericos(dados)
if len(lista_filtrada) == 0:
print("Nenhum número disponível.")
return None
if len(lista_filtrada) == 1:
print("Apenas um número:", lista_filtrada[0])
return None
valor_maximo = max(lista_filtrada)
ocorrencias = lista_filtrada.count(valor_maximo)
while ocorrencias > 0:
lista_filtrada.remove(valor_maximo)
ocorrencias -= 1
if not lista_filtrada:
return None
return max(lista_filtrada)
Método 3: Ordenação com Valores Únicos
Utilizamos ordenação após remover duplicatas para obter uma lista ordenada de valores distintos.
def obter_segundo_maior_metodo3(dados):
lista_filtrada = filtrar_elementos_numericos(dados)
if len(lista_filtrada) == 0:
print("Lista vazia após filtragem.")
return None
if len(lista_filtrada) == 1:
print("Apenas um número:", lista_filtrada[0])
return None
lista_sem_duplicatas = list(set(lista_filtrada))
lista_sem_duplicatas.sort(reverse=True)
if len(lista_sem_duplicatas) >= 2:
return lista_sem_duplicatas[1]
return None
Método 4: Empregando heapq
Arpoveitamos a heapq para extrair os maiores valores de forma eficiente.
import heapq
def obter_segundo_maior_metodo4(dados):
lista_filtrada = filtrar_elementos_numericos(dados)
if len(lista_filtrada) == 0:
print("Sem elementos numéricos.")
return None
if len(lista_filtrada) == 1:
print("Apenas um número:", lista_filtrada[0])
return None
lista_sem_duplicatas = list(set(lista_filtrada))
if len(lista_sem_duplicatas) >= 2:
return heapq.nlargest(2, lista_sem_duplicatas)[1]
return None
Ao executar os testes, verifique se os caminhos de importação estão configurados corretamente no seu ambiente.
