MAC2166 - Introdução à Computação

25/04/2017 - Aula 9

Listas - estruturas sequenciais indexadas

Em Python, podemos manipular listas. Uma lista é uma sequência de valores. Os valores em uma lista são chamados de elementos ou itens.

O modo mais simples de se criar uma lista é envolver seus elementos com um par de chaves. O tipo de uma lista é list.

In [1]:
lista1 = [4, 2, 9]     # cria uma lista com três números inteiros, os números 4, 2 e 9
print(type(lista1))    
print("O conteúdo da lista é:", lista1)
print("A quantidade de elementos da lista é:", len(lista1))
<class 'list'>
O conteúdo da lista é: [4, 2, 9]
A quantidade de elementos da lista é: 3

Para obter o comprimento de uma lista (ou seja, o número de elementos que a lista possui) usamos a função len() (de length), como mostrado no exemplo acima.

[] denota uma lista vazia, ou seja, uma lista que não contém nenhum elemento. O comprimento de uma lista que não contém nenhum elemento é 0.

In [2]:
lista2 = []     # cria uma lista vazia, ou seja com nenhum elemento dentro dela
print("O conteúdo da lista é:", lista2)
print("A quantidade de elementos da lista é:", len(lista2))
O conteúdo da lista é: []
A quantidade de elementos da lista é: 0

Usando o operador * conseguimos criar rapidamente listas de um determinado comprimento contendo elementos iguais. Veja os exemplos.

In [4]:
lista3 = [3] * 10   # criar uma lista contendo 10 elementos, todos de valor 3
tamanho = len(lista3) 
print("Lista com",len(lista3),"elementos de valor 3:",lista3)
print()
lista3 = [1,2,3] * 5 
print("Lista com 5 subsequências repetidas:",lista3)
Lista com 10 elementos de valor 3: [3, 3, 3, 3, 3, 3, 3, 3, 3, 3]

Lista com 5 subsequências repetidas: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

Os elementos em uma lista não precisam ser todos de um mesmo tipo, como mostra o exemplo a seguir:

In [5]:
lista4 = ["Hello", 2, 5.6, "World", 15]
print("Uma lista com elementos de diferentes tipos:", lista4)
Uma lista com elementos de diferentes tipos: ['Hello', 2, 5.6, 'World', 15]

Usamos l[i] para nos referir à posição de número (= índice) i uma lista l, sendo que a primeira posição de uma lista é a de índice 0, a segunda é a de índice 1, e assim por diante, até a última posição da lista - que tem índice len(l)-1. Veja os exemplos a seguir:

In [6]:
lista5 = [10, 20, 30, 40, 50]
print(lista5[0])      # mostra o valor do primeiro elemento da lista
print(lista5[2])
print(lista5[4])      # mostra o valor do último elemento da lista
print(lista5[len(lista5)-1])   # também mostra o valor do último elemento da lista
10
30
50
50

Podemos usar números negativos como índices para acessar as posições de uma lista na ordem reversa, ou seja, do fim para o início. O índice -1 se refere a última posição da lista, o -2 se refere à penúltima posição, e assim por diante.

In [7]:
lista5 = [10, 20, 30, 40, 50]
print(lista5[-1])             # mostra o valor do último elemento da lista
print(lista5[-len(lista5)])   # mostra o valor do primeiro elemento da lista
50
10

Também é possível modificar o valor de uma posição específica da lista:

In [8]:
lista6 = [10, 20, 30]
print(lista6)
lista6[0] = 5      # altera o valor da primeira posição da lista
lista6[-1] //= 2   # altera o valor da última posição da lista
print(lista6)
[10, 20, 30]
[5, 20, 15]

Quanto tentamos acessar uma posição que não existe na lista, um erro de execução list index out of range é gerado:

In [9]:
lista7 = [10, 20]
print(lista7[2])   # tenta exibir o valor de uma posição que não existe na lista
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-9-65b8d9d88670> in <module>()
      1 lista7 = [10, 20]
----> 2 print(lista7[2])   # tenta exibir o valor de uma posição que não existe na lista

IndexError: list index out of range

Podemos usar a função append() para acrescentar novos elementos em uma lista. Para acrescenter o elemento x ao final de uma lista l, fazemos l.append(x). Veja os exemplos a seguir:

In [10]:
lista8 = [40]
print("Estado inicial da lista: ", lista8)
lista8.append(10)
print("Estado da lista depois da primeira inclusão de um novo elemento: ", lista8)
lista8.append(30)
print("Estado da lista depois da segunda inclusão de um novo elemento: ", lista8)
Estado inicial da lista:  [40]
Estado da lista depois da primeira inclusão de um novo elemento:  [40, 10]
Estado da lista depois da segunda inclusão de um novo elemento:  [40, 10, 30]

Embora os elementos de uma lista também possam ser percorridos por meio de um laço tradicional (os que vimos nas aulas anteriores), existe um tipo de laço for especial para percorrer todos os elementos de lista, começando do seu início para o fim. A estrutura desse laço é

for elemento in lista:

onde elemento é o nome da variável que receberá um elemento da lista e lista é uma lista de elementos. Exemplo:

In [11]:
lista9 = [10, 20, 30, 40]
soma = 0
for numero in lista9:
    print(numero)
    soma += numero
print("A soma é", soma)
10
20
30
40
A soma é 100

Finalmente, o operador in nos permite verificar se um dado valor está em uma lista. A expressão

valor in lista

devolve True se valor for um elemento de lista, e False no caso contrário.

In [12]:
lista10 = [0,2,4,6,8,10]
print(lista10)
if 4 in lista10:
    print("O valor 4 está na lista.")
if 3 not in lista10:
    print("O valor 3 não está na lista.")
[0, 2, 4, 6, 8, 10]
O valor 4 está na lista.
O valor 3 não está na lista.

Problema 9.1

Dados n > 0 e uma sequência com n números reais, imprimi-los na ordem inversa à da leitura.

Obs.: Este problema corresponde ao exercício 1 da lista de exercícios sobre vetores.

In [2]:
#--------------------------------------------
# Programa principal
def main():
    print ("Lê n números reais e imprime-os em ordem reversa")
    n = int(input("Digite n: "))
    cont = 0
    seq = []  # cria uma lista vazia

    while cont < n:
        num = float(input("Digite um número da sequência: "))
        seq.append(num)   # coloca num no final da lista
        cont += 1

    print("Sequência original: ", seq)


    print("Solução 1: usando índices decrescentes")
    cont = n-1
    while cont >= 0:
        print (seq[cont], end=' ')
        cont -= 1
    print ()

    # ou ainda, usando índices negativos
    print("Solução 2: usando índices negativos")
    cont = -1
    while cont >= -n:
        print (seq[cont], end=' ')
        cont -= 1
    print()
    
#--------------------------------------------    
main()
Lê n números reais e imprime-os em ordem reversa
Digite n: 4
Digite um número da sequência: 2.3
Digite um número da sequência: 67.345
Digite um número da sequência: 1
Digite um número da sequência: 93.45
Sequência original:  [2.3, 67.345, 1.0, 93.45]
Solução 1: usando índices decrescentes
93.45 1.0 67.345 2.3 
Solução 2: usando índices negativos
93.45 1.0 67.345 2.3 

Observação: no Python, é possível usar a função reverse() de um objeto do tipo List que inverte a ordem dos elementos de uma lista. Mas é preciso ter cuidado ao usar essa função, por que ela modifica a lista a partir da qual ela foi chamada. Além disso, é muito importante saber percorrer uma lista da forma tradicional, em ordem "normal" ou inversa, usando um laço while ou for, já que muitas linguagens não possuem uma função equivalente à reverse().

Usando a função reverse(), a solução do Problema 9.1 fica como a mostrada a seguir:

In [1]:
#--------------------------------------------
# Programa principal
def main():
    print ("Lê n números reais e imprime-os em ordem reversa")
    n = int(input("Digite n: "))
    cont = 0
    seq = []  # cria uma lista vazia

    while cont < n:
        num = float(input("Digite um número da sequência: "))
        seq.append(num)   # coloca num no final da lista
        cont += 1

    print("Sequência original: ", seq)

    # ou ainda, usando a função reverse()
    seq.reverse()         # inverte a ordem dos elementos da lista
    print("Solução 3: usando a função reverse()")
    print(seq)

#----------------------------------------------
main()
Lê n números reais e imprime-os em ordem reversa
Digite n: 4
Digite um número da sequência: 2.3
Digite um número da sequência: 67.345
Digite um número da sequência: 1
Digite um número da sequência: 93.45
Sequência original:  [2.3, 67.345, 1.0, 93.45]
Solução 3: usando a função reverse()
[93.45, 1.0, 67.345, 2.3]

Problema 9.2

Dadas n notas de provas, calcular a sua média e o número de notas acima da média calculada.

Solução 1 ( usa for var in range(...))

In [2]:
def main():
    '''
    Programa que le n notas de provas, calcula a media
    das notas da prova e imprime o numero de notas
    maiores que a media calculada.
    '''

    # leia o numero de notas
    n = int(input("Digite o número de notas: "))

    # inicializacoes
    soma_notas = 0
    lista_notas = []

    # calcule a soma das notas e crie uma lista com
    # as notas
    for i in range(n):
        nota = float(input("Digite uma nota: "))
        soma_notas += nota
        lista_notas.append(nota)

    # calcule a media
    media_notas = soma_notas/n
    print("A media das notas e %.1f" %(media_notas))

    # conte quantas notas estao acima da media
    cont = 0
    for i in range(n):
        if lista_notas[i] > media_notas:
            cont += 1

    print("%d notas sao maiores que %.1f"
          %(cont, media_notas))

#----------------------------------------------------
main()
Digite o número de notas: 5
Digite uma nota: 5.6
Digite uma nota: 9.8
Digite uma nota: 3.1
Digite uma nota: 4.5
Digite uma nota: 7.3
A media das notas e 6.1
2 notas sao maiores que 6.1

Solução 2 (usa for objeto in lista)

In [4]:
def main():
    '''
    Programa que le n notas de provas, calcula a media
    das notas da prova e imprime o numero de notas
    maiores que a media calculada.
    '''

    # leia o numero de notas
    n = int(input("Digite o número de notas: "))

    # inicializacoes
    soma_notas = 0
    lista_notas = []

    # calcule a soma das notas e crie uma lista com
    # as notas
    for i in range(n):
        nota = float(input("Digite uma nota: "))
        soma_notas += nota
        lista_notas.append(nota)

    # calcule a media
    media_notas = soma_notas/n
    print("A media das notas e %.1f" %(media_notas))

    # conte quantas notas estao acima da media
    cont = 0
    for nota in lista_notas:
        if nota > media_notas:
            cont += 1

    print("%d notas sao maiores que %.1f" %(cont, media_notas))

#----------------------------------------------------
main()
Digite o número de notas: 5
Digite uma nota: 5.6
Digite uma nota: 9.8
Digite uma nota: 3.1
Digite uma nota: 4.5
Digite uma nota: 7.3
A media das notas e 6.1
2 notas sao maiores que 6.1

Problema 9.3

Dados n > 0 lançamentos de uma roleta (números entre 0 e 36), calcular a frequência de cada número.

In [11]:
#--------------------------------------------
# Programa principal
def main():
    print ("Frequência relativa de n lançamentos de uma roleta")
    n = int(input("Digite n: "))
    cont = 0
    seq = [0] * 37   # cria uma lista de 37 posições com zeros

    while cont < n:
        cont += 1
        num  = int(input("Digite o resultado do lançamento %d: "%(cont)))
        seq[num] += 1

    i = 0
    for freq in seq:
        if freq > 0:
            print("frequência dos números sorteados %d = %5.2f" %(i, freq/n))
        i += 1

    # ou ainda, usando as funções range() e len()
    print("Outra solução")
    for i in range(len(seq)):
        if seq[i] > 0:
            print ("frequência dos números sorteados %d = %5.2f" %(i, seq[i]/n))

#--------------------------------------------
main()
Frequência relativa de n lançamentos de uma roleta
Digite n: 5
Digite o resultado do lançamento 1: 13
Digite o resultado do lançamento 2: 5
Digite o resultado do lançamento 3: 13
Digite o resultado do lançamento 4: 30
Digite o resultado do lançamento 5: 5
frequência dos números sorteados 5 =  0.40
frequência dos números sorteados 13 =  0.40
frequência dos números sorteados 30 =  0.20
Outra solução
frequência dos números sorteados 5 =  0.40
frequência dos números sorteados 13 =  0.40
frequência dos números sorteados 30 =  0.20

Problema 9.4

Dados dois números naturais m e n e duas sequências ordenadas com m > 0 e n > 0 números inteiros, criar uma nova lista contendo a sequência ordenada com todos os elementos das sequências originais sem repetição.

Obs.: Este problema corresponde ao exercício 8 da lista de exercícios sobre vetores.

Solução 1

In [12]:
# Lê os elementos da primeira sequencia 
m = int(input("Digite m: "))
cont1 = 0
seq1 = []
while cont1 < m:
    cont1 += 1
    num = int(input("Digite o número %d da sequencia 1: "%(cont1)))
    seq1.append(num)
    
print()

# Lê os elementos da segunda sequencia 
n = int(input("Digite n: "))
cont2 = 0
seq2 = []
while cont2 < n:
    cont2 += 1
    num = int(input("Digite o número %d da sequencia 2: "%(cont2)))
    seq2.append(num)

# Cria a sequencia ordenada a partir das duas outras
seq_ordenada = []    

cont1 = 0
cont2 = 0

# Intercala os elementos de forma ordenada até que uma das listas chegue ao fim
while cont1 < m and cont2 < n:
    if seq1[cont1] <= seq2[cont2]:
        # Só insere se não for repetido
        if len(seq_ordenada) == 0 or seq1[cont1] != seq_ordenada[-1]:
            seq_ordenada.append(seq1[cont1])
        cont1 += 1
    else:
        if len(seq_ordenada) == 0 or seq2[cont2] != seq_ordenada[-1]:
            seq_ordenada.append(seq2[cont2])
        cont2 += 1

# Inclui na lista ordenada os elementos restantes da lista que não foi 
# percorrida até o fim no laço anterior
while cont1 < m:
    if len(seq_ordenada) == 0 or seq1[cont1] != seq_ordenada[-1]:
        seq_ordenada.append(seq1[cont1])
    cont1 += 1
    
while cont2 < n:
    if len(seq_ordenada) == 0 or seq2[cont2] != seq_ordenada[-1]:
        seq_ordenada.append(seq2[cont2])
    cont2 += 1
    
print(seq_ordenada)
Digite m: 3
Digite o número 1 da sequencia 1: 1
Digite o número 2 da sequencia 1: 2
Digite o número 3 da sequencia 1: 4

Digite n: 5
Digite o número 1 da sequencia 2: 2
Digite o número 2 da sequencia 2: 3
Digite o número 3 da sequencia 2: 4
Digite o número 4 da sequencia 2: 5
Digite o número 5 da sequencia 2: 6
[1, 2, 3, 4, 5, 6]

Solução 2 (usando funções)

In [13]:
def main():
    '''
    Dados m e n e duas sequencias ordenadas com m e n numeros inteiros
    criar uma nova lista ordenada com todos os elementos das sequencias originais
    sem repeticoes
    '''

    # le os elementos da primeira sequencia
    print("Iniciando leitura da primeira sequencia: ")
    seq_1 = le_sequencia()
    print("Sequencia 1:", seq_1)

    # le os elementos da segunda sequencia
    print("Iniciando leitura da segunda sequencia ordenada: ")
    seq_2 = le_sequencia()
    print("Sequencia 2:", seq_2)

    # intercale as duas sequencia eleminando as possiveis repeticoes
    # neste cada seq_i eh formada por elementos distintos.
    seq_final = intercala(seq_1,seq_2)

    print("Sequencia ordenada e sem repeticoes:", seq_final)

#------------------------------------------------------------
def le_sequencia():
    '''(None) -> list

    Le do teclado uma sequencia de numeros inteiros e retorna
    uma lista com os elementos lidos.

    Observacoes: a lista retornada nao tem elementos repetidos.
    '''
    seq = []
    n = int(input("Digite o tamanho da sequencia:"))
    for i in range(n):
        # le o proximo numero da sequencia
        num = int(input("Digite o %do. numero da sequencia: " %(i+1)))

        # procura o numero lido na lista
        achou = pertence(num,seq) # equivalente a: achou = num in seq

        # verifica se o numero lido deve ser inserido na lista
        if not achou:
            seq.append(num)

    return seq

#-------------------------------------------------
def intercala(lista_1, lista_2):
    '''(list, list) -> list

    Recebe lista_1 e lista_2 que sao listas ordenadas de numeros.
    Retorna uma lista ordenada dos numeros contido nas listas
    dadas, sem repeticoes.
    
    '''
    lista = []
    i = 0 # percorre lista 1
    len_1 = len(lista_1)
    j = 0 # percorre lista 2
    len_2 = len(lista_2)
    while i < len_1 or j < len_2:
        if i == len_1:   # ja incluiu na nova lista todos os itens da lista 1
            lista.append(lista_2[j])
            j += 1
        elif j == len_2:   # ja incluiu na nova lista todos os itens da lista 2
            lista.append(lista_1[i])
            i += 1
        elif lista_1[i] == lista_2[j]:  
            lista.append(lista_1[i])
            i += 1
            j += 1
        elif lista_1[i] < lista_2[j]:
            lista.append(lista_1[i])
            i += 1
        else:
            lista.append(lista_2[j])
            j += 1

    return lista

#-------------------------------------------------
def pertence(item,lista):
    '''(objeto, list) -> bool

    Recebe uma lista de itens e um item e
    retorna True se o item eh um elemento da lista e
    False em caso contrario.
    '''
    achou = False
    j = 0
    while j < len(lista) and not achou:
        if item == lista[j]:
            achou = True
        j = j + 1

    return achou

#---------------------------------------
main()
Iniciando leitura da primeira sequencia: 
Digite o tamanho da sequencia:3
Digite o 1o. numero da sequencia: 1
Digite o 2o. numero da sequencia: 2
Digite o 3o. numero da sequencia: 4
Sequencia 1: [1, 2, 4]
Iniciando leitura da segunda sequencia ordenada: 
Digite o tamanho da sequencia:5
Digite o 1o. numero da sequencia: 2
Digite o 2o. numero da sequencia: 3
Digite o 3o. numero da sequencia: 4
Digite o 4o. numero da sequencia: 5
Digite o 5o. numero da sequencia: 6
Sequencia 2: [2, 3, 4, 5, 6]
Sequencia ordenada e sem repeticoes: [1, 2, 3, 4, 5, 6]

Tópicos vistos na aula 9

Sobre Listas - estruturas sequenciais indexadas:

  • Como criar e acessar o conteúdo de uma lista
  • Função len() - para obter o número de elementos de uma lista
  • Função append() - para adicionar um elemento no final da lista
  • Comando for elem in lista para percorrer os elementos de uma lista