Algorismes sobre seqüències

Llistes per comprensió

  • Una llista per comprensió és una sintaxi compacta per calcular una llista processant tots o part dels elements d’una term:seqüència

  • La notació s’inspira en la de construcció de conjunts

  • Exemples

    • Llista amb els nombres d’una altra llista en valor absolut

      >>> nombres = [-15, 9, 2, -5, -8, 4]
      >>> nombres_abs = [abs(n) for n in nombres]
      >>> nombres_abs
      [15, 9, 2, 5, 8, 4]
      
    • Llista amb els nombres parells d’una seqüència elevats al quadrat

      >>> a = 7, -1, 4, 5, 2, -6
      >>> b = [x**2 for x in a if x%2 == 0]
      >>> b
      [16, 4, 36]
      

Recorregut dels elements d’una seqüència

  • La sentència for permet recórrer els elements d’una seqüència i executar les sentències per cada un d’ells

    for element in seqüència:
        sentències
    
    • element és una variable

    • seqüència és una expressió que s’avalua a una seqüència

    • sentències són un bloc de sentències sagnades respecte de la capçalera

  • Iterar és repetir l’execució d’un bloc de codi

  • Com que la sentència for permet iterar direm que és una (sentència d’iteració)

  • També diem iteració a l’execució de les sentències per un concret d'element

  • Esquemes

Recorreguts per generar llistes

Esquema aplica

Genera una llista a partir d’una seqüència en què cada element de la llista es calcula aplicant (cridant) una funció sobre l’element corresponent de la seqüència.

Per exemple:

L’esquema general és

def aplica(seqüència, funció):
    r = []
    for elem in seqüència:
        elem_r = funció(elem)
        r.append(elem_r)
    return r

on només cal decidir

  1. quina és la funció que cal aplicar a cada element (funció).

Les llistes per comprensió permeten obtenir el mateix resultat:

r = [funció(elem) for elem in seqüència]

Esquema Filtra

Genera una llista que conté els elements de la seqüència que compleixen una condició.

Per exemple:

L’esquema general és

def filtra(seqüència, condició):
    r = []
    for elem in seqüència:
        if condició(elem):
            r.append(elem)
    return r

on només cal decidir

  1. quina és la condició que han de complir els elements triats (condició).

Les llistes per comprensió permeten obtenir el mateix resultat:

r = [elem for elem in seqüència if condició(elem)]

Recorregut per sintetitzar

Calcula un resultat que sintetitza els valors dels elements de la seqüència.

Per exemple:

  • sumar els elements (sum()),

  • calcular el màxim (max()) o el mínim (min()),

  • comptar els elements (len()),

  • concatenar els elements d’una llista d'strings (str.join()).

  • Mesures, mitjana

L’esquema general és

def sintetiza(seqüència, acumula, element_neutre_acumula):
    s = element_neutre_acumula
    for elem in seqüència:
        s = acumula(s, elem)
    return s

on només cal decidir

  1. quina és l’operació acumula, i

  2. quin és l’element neutre d’aquesta operació (element_neutre_acumula)

Cercar en una seqüència

Decidir si algun dels elements d’una seqüència compleix una condició.

Per exemple:

L’esquema general és

def cerca(seqüència, condició):
    trobat = False
    for elem in seqüència:
        trobat = condició(elem)
        if trobat:
            break
    return trobat

on només cal decidir

  1. quina és la condició que ha de complir l’element que busquem (condició).

Combinacions d’esquemes

  • Qualsevol combinació de sintetitza, aplica, filtra i cerca.

  • Les llistes per compressió combinen els esquemes de filtra i aplica:

    r = [funció(elem) for elem in seqüència if condició(elem)]
    
  • Exemples:

Recorregut en paral·lel

  • Recorregut dels elements de dues o més seqüències en paral·lel

  • Per exemple:

  • La funció zip() agrupa en una tupla els elements de la mateixa posició de dues o més seqüències

    >>> seq_a = ['m', 'x', 'r']
    >>> seq_b = [7, 3, 5]
    >>> r = []
    >>> for a, b in zip(seq_a, seq_b):
    ...     r.append(a*b)
    >>> ', '.join(r)
    'mmmmmmm, xxx, rrrrr'
    

El tipus range

  • range(a, b, d) retorna un objecte de tipus range que representa els elements de la progressió aritmètica \(a + nd\) per \(n \ge 0\) que són més petits que \(b\)

    >>> r = range(3, 10, 2)
    >>> list(r)
    [3, 5, 7, 9]
    
  • El tipus range és un tipus seqüència: admet les Operacions comunes als tipus seqüència i la Conversió de tipus

  • Els objectes de tipus range són immutables

  • d es pot ometre: range(a, b) equival a range(a, b, 1)

    >>> r = range(5, 8)
    >>> list(r)
    [5, 6, 7]
    >>> s = range(5, 8, 1)
    >>> list(s)
    [5, 6, 7]
    
  • a també es pot ometre: range(b) equival a range(0, b, 1)

    >>> r = range(5)
    >>> list(r)
    [0, 1, 2, 3, 4]
    >>> s = range(0, 5, 1)
    >>> list(s)
    [0, 1, 2, 3, 4]
    
  • d pot ser negatiu. Aleshores a > b

    >>> r = range(8, 3, -1)
    >>> list(r)
    [8, 7, 6, 5, 4]
    

Recorregut dels índexs d’una seqüència

  • Usant for i range

    for índex in range(len(seqüència)):
        sentències
    
  • Usant for i enumerate()

    for índex, element in enumerate(seqüència):
        sentències
    

Quan cal recórrer els índexs?

  • Quan el resultat és un índex (o posició)

    • índex del primer nombre negatiu

  • Quan cal modificar algun element de la llista

  • Quan cal desplaçar finestres

Seqüències imbricades

  • Seqüència imbricada: seqüència en què almenys un dels seus elements és una altra seqüència

  • Exemples d’accés

  • L’operador claudàtor s’avalua d’esquerra a dreta

  • Exemples:

Matrius

  • Les llistes imbricades es poden usar per representar matrius

    >>> matrix = [
    ...   [1, 2, 3],
    ...   [4, 5, 6],
    ...   [7, 8, 9]
    ... ]
    >>> matrix[1]
    [4, 5, 6]
    >>> matrix[1][1]
    5
    

    Atenció

    En crear una matriu, cal garantir que cada fila és una llista diferent. Vegeu python:faq-multidimensional-list.

Ordenar

Generar una llista ordenada

  • La funció sorted() retorna una llista ordenada que conté els elements d’una seqüència

    >>> t = (7, 3, 5, 1, 4)
    >>> l = sorted(t)
    >>> l
    [1, 3, 4, 5, 7]
    
  • Exemples

Ordenar una llista

  • El mètode sort() reordena els elements de la llista per tal que quedi ordenada. Per tant, modifica la llista

    >>> l = [7, 3, 5, 1, 4]
    >>> l.sort()
    >>> l
    [1, 3, 4, 5, 7]
    
  • Exemples

Ordenar decreixentment, paràmetre reverse

  • El mètode sort() de llistes i la funció sorted() tenen un paràmetre opcional booleà reverse que per defecte val False

  • Si reverse és False, ordena creixentment

  • Si reverse és True, ordena decreixentment

  • Exemples

El paràmetre key

  • El mètode sort() de llistes i les funcions sorted(), min() i max() tenen un paràmetre opcional key

  • El paràmetre opcional key és útil quan cal comparar els elements de la llista per un criteri diferent de l’ordre estàndard

  • Exemples

    • Donada una llista d’strings ordenar-la per la longitud dels strings en comptes de per ordre lexicogràfic

      >>> ls = ['lluna', 'estrella', 'sol']
      >>> ls.sort(key=len)
      >>> ls
      ['sol', 'lluna', 'estrella']
      
    • Notes: 8

    • Tarifa plana: 7

    • Natació (4 punts): 2

Expressions lambda

Vegeu python:lambda

  • Permeten escriure funcions anònimes molt senzilles d’una manera sintètica

  • Sovint s’usen com a arguments de funcions, per exemple, del paràmetre key

    >>> temps = ['9:15', '09:27', '05:07', '5:4']
    >>> sorted(temps, key=lambda t: [int(c) for c in t.split(':')])
    ['5:4', '05:07', '9:15', '09:27']