Una seqüència és un conjunt d'elements agrupats un a continuació de l'altre.

Introducció

Una manera habitual d'agrupar un conjunt de valor és mitjançant una seqüencia.

array

Typescript té una estructura de dades de tipus [] que es fa servir per guardar els elements que tu vulguis en una "array".

Edita el fitxer main.ts:

{
    const list: number[] = [6, 8, 11]
}

Com que els elements de l'array estan ordenats pots accedir a cada elements per la seva posició dins de l'array.

[ 0 ] => 6
[ 1 ] => 8
[ 2 ] => 11

Només has de tenir en compte que es comença a contar des del número 0.

Has d'accedir indicant la posició entre claudators:

{
    const list: number[] = [6, 8, 11]
    console.log(list[0]) // 6
    console.log(list[1]) // 8
    console.log(list[2]) // 11
}

A continuació tens una llista de fruites:

{
    const fruits: string[] = ["Apple", "Orange", "Plum"]
}

Que passa si intentes accedir al cinquè element de la llista?

{
    const fruits: string[] = ["Apple", "Orange", "Plum"]
    const fruit = fruits[4]
    console.log(fruit)
}

Executem el codi:

$ bun main.ts
undefined

Que els valor de la variable fruit és undefined perquè la llista només té tres elements.

Si vols pots modificar un element de la llista indicant la seva posició:

{
    const fruits: string[] = ["Apple", "Orange", "Plum"]
   
    fruits[1] = "Banana"
    console.log(fruits) // [ "Apple", "Banana", "Plum" ]
}

També pots saber la mida d'una llista amb la propietat length:

{
    const fruits: string[] = ["Apple", "Orange", "Plum"]
    console.log(fruits.length) // 3
}

Si vols pots afegir elements a una llista:

{
    const fruits: string[] = []
    fruits.push("Banana")
    fruits.push("Apricot")
    fruits.push("Cherry")

    console.log(fruits) // [ "Banana", "Apricot", "Cherry" ]
}

Els elements sempre s'afegeixen al final de la llista.

Bucle

Una de les operacions més habituals amb un array és recorrer tots els elements de la llista.

Amb for .. of pots recorrer tots els elements d'una llista:

{
    const fruits: string[] = ["Apple", "Orange", "Apricot", "Plum"]

    for(const fruit of fruits) {
        console.log(fruit)
    }
}

A continuació et mostrarem algunes solucions que no són del tot eficients, de moment!

Un codi primer ha de funcionar, després ha de funcionar bé, i per últim funcionar ràpid.

I el més important, un codi s'ha de poder llegir i entendre a la primera.

map

Una operació habitual és transformar una llista aplicant una transformació a cada element de la llista:

A continuació tens un exemple:

{
    
    const xs: number[] = [8, 9, 4, 5, 6]

    const ys: number[] = []
    for (const x of xs) {
        ys.push(x * 2)
    }

    console.log(ys) // [ 16, 18, 8, 10, 12 ]
}

filter

Una altre operació habitual és filtrar els elements d'una llista.

Per exemple, només vols una llista amb els valors més grans que 5:

{
    
    const xs: number[] = [8, 9, 4, 5, 6]

    const ys: number[] = []
    for (const x of xs) {
        if (x > 5)
            ys.push(x)
    }

    console.log(ys) // [ 8, 9, 6 ]
}

reduce

Un algoritme habitual en llistes es reduir la llista a un sol valor.

Per exemple, pots sumar tots els elements de la llista:

{
    const xs: number[] = [8, 9, 4, 5, 6, 2, 9, 4, 7, 2, 3]

    let sum = 0 // valor inicial
    for (const x of xs) {
        sum += x
    }

    console.log(sum) //50
}

Calcula la mitjana aritmètica de la llista:

{
    const xs: number[] = [8, 9, 4, 5, 6, 2, 9, 4, 7, 2, 3]

    let sum = 0 // valor inicial
    for (const x of xs) {
        sum += x
    }

    const mean = sum / xs.length
    console.log(mean) //5.36
}

find

Una altra operació habitual és buscar si una llista té un element.

{

    const target = "Apricot"
    const fruits: string[] = ["Apple", "Orange", "Apricot", "Plum"]

    let result = false
    for (const fruit of fruits){
        if (fruit == target) {
            result = true
            break
        }
    }

    console.log(result)  // true
}

Activitat

1.- Tens una llista xs de tipus number[].

Busca el valor màxim de la llista

{
   const xs: number[] = [8, 9, 4, 5, 6, 2, 9, 4, 7, 2, 3]

   // ...

   console.log(max) // 9
}

{
    const xs: number[] = [8, 9, 4, 5, 6, 2, 9, 4, 7, 2, 3]

    let max = xs[0] // valor inicial
    for (const x of xs) {
        if (x > max)
            max = x
    }

    console.log(max) // 9
}

2.- A continuació tens una llista de persones:

{
    const xs: string[] = ["Olivia Anderson", "Ethan Carter", "Isabella Brooks",
        "Olivia Bennett", "Ava Morgan", "Noah Mitchell", "Mia Harper", "Liam Parker"]
}

Crea una nova llista només amb les persones que el seu nom és Olivia.

"Olivia Bennet".startsWith("Olivia") // true

{
    const xs: string[] = ["Olivia Anderson", "Ethan Carter", "Isabella Brooks",
        "Olivia Bennett", "Ava Morgan", "Noah Mitchell", "Mia Harper", "Liam Parker"]

    const result: string[] = []
    for (const x of xs) {
        if (x.startsWith("Olivia"))
            result.push(x)
    }

    console.log(result) // [ "Olivia Anderson", "Olivia Bennett" ]
}

3.- Molts cops tens una llista de notes en que et falta alguna nota perque l'alumne no ha fet l'examen.

Calcula la mitjana aritmètica d'aquesta llista:

{
    const xs: (number| null) [] = [8, 9, 4, 5, null, 6, 2, 9, null, 4, 7, 2, 3]

    // ...

    console.log(mean) //5.36

}

{
    const xs: (number| null) [] = [8, 9, 4, 5, null, 6, 2, 9, null, 4, 7, 2, 3]

    // Creem una llista nova sense els valors null
    const ys: number[] = []
    for (const x of xs) {
        if (x == null) // si un element és null no el processem
            continue
        ys.push(x)
    }


    // Sumem tots els valors de la llista filtrada
    let sum = 0 // valor inicial
    for (const y of ys) {
        sum += y
    }

    // Calculem la mitjana aritmètica
    const mean = sum / ys.length

    console.log(mean) //5.36

}

Llistes imbricades

Una llista pot estar formada per llistes:

{
    const xss: number[][] = [
        [3, 4, 5, 2, 3, 8],
        [9, 1, 4, 9, 1],
        [1, 2, 0, 9]
    ]
}

Per processar aquesta llista necessites escriure dos bucles.

Per exemple, pots afegir tots els números en una sola llista:

{
    const xss: number[][] = [
        [3, 4, 5, 2, 3, 8],
        [9, 1, 4, 9, 1],
        [1, 2, 0, 9]
    ]


    const ys: number[] = []
    for (const xs of xss) {
        for (const x of xs) {
            ys.push(x)
        }
    }

    console.log(ys) // [3, 4, 5, 2, 3, 8, 9, 1, 4, 9, 1, 1, 2, 0, 9]
}

Activitats

1.- Crea una llista amb les sumes de cada llista.

{
    const xss: number[][] = [
        [3, 4, 5, 2, 3, 8],
        [9, 1, 4, 9, 1],
        [1, 2, 0, 9]
    ]

    // ...

    console.log(ys) // [ 25, 24, 12 ]
}

{
    const xss: number[][] = [
        [3, 4, 5, 2, 3, 8],
        [9, 1, 4, 9, 1],
        [1, 2, 0, 9]
    ]


    const ys: number[] = []
    for (const xs of xss) {
        let y = 0
        for (const x of xs) {
            y += x
        }
        ys.push(y)
    }

    console.log(ys) // [ 25, 24, 12 ]
}

2.- Crea una llista amb la mitja aritmètica de cada llista.

{
    const xss: number[][] = [
        [3, 4, 5, 2, 3, 8],
        [9, 1, 4, 9, 1],
        [1, 2, 0, 9]
    ]

    // ...

    console.log(ys) // [ 4.16, 4.8, 3 ]
}

{
    const xss: number[][] = [
        [3, 4, 5, 2, 3, 8],
        [9, 1, 4, 9, 1],
        [1, 2, 0, 9]
    ]


    const ys: number[] = []
    for (const xs of xss) {
        let sum = 0
        for (const x of xs) {
            sum += x
        }
        ys.push(sum / xs.length)
    }

    console.log(ys) // [ 4.16, 4.8, 3 ]
}

}

Slice

La funció slice(start,end) torna una vista parcial de la llista.

{
    const xs: string[] = ["ant", "bison", "camel", "duck", "elephant"]

    const ys = xs.slice(0, 2)
    console.log(ys) // [ "ant", "bison" ]
}

El segon paràmetre és opcional:

{
    const xs: string[] = ["ant", "bison", "camel", "duck", "elephant"]

    const ys = xs.slice(3)
    console.log(ys) // [ "duck", "elephant" ]
}

També pots utilitzar index negatius (comencen a contar al revés de dreta a esquerra):

{
    const xs: string[] = ["ant", "bison", "camel", "duck", "elephant"]

    const ys = xs.slice(1, -1)
    console.log(ys) // [ "bison", "camel", "duck" ]
}

La funció slice és útil quan només vols processar un conjunt d'elements de la llista.

{
    const xs: number[] = [3, 4, 5, 2, 3, 8, 9, 1, 4, 9, 1, 1, 2, 0, 9]

    let sum = 0
    for (const x of xs.slice(0,3)) {
        sum += x
    }
    console.log(sum) // 12
}

Funcions

A Funcions veurem que són les funcions "arrow".

Però és important que entenguis perquè treballem amb les llistes com hem estat fent fins ara.

La majoria de les vegades les llistes no es processen amb for .. of, sinó que es processen amb funcions de manera funcional.

Les operacions bàsiques són: map, filter, reducei find.

Amb la funció map pots aplicar una funció a cada element de la llista creant una nova llista:

{
    const xs: number[] = [8, 9, 4, 5, 6]

    const ys = xs.map(x => x * 2)

    console.log(ys) // [ 16, 18, 8, 10, 12 ]
}

Amb la funció reduce pots sumar tots els elements d'una llista:

{
    const xs: number[] = [8, 9, 4, 5, 6]

    const sum = xs.reduce((acc, x) => acc + x, 0) // acc: accumulator

    console.log(sum) // 32
}

Amb la funció filter pots filtrar els elements d'una llista:

{
    const xs: (number | null)[] = [8, 9, null, 4, 5, null, 6]

    const ys = xs.filter(value => value != null)

    console.log(ys) // [ 8, 9, 4, 5, 6 ]
}

Pots aplicar les funcions una darrera l'altre:

{
    const xs: (number | null)[] = [8, 9, null, 4, 5, null, 6]

    const ys = xs.
        filter(value => value != null).
        map(x => x * 5).
        reduce((acc, x) => acc + x)

    console.log(ys) // 160
}

Activitats

1.- Calcula la mitjana aritmètica dels 5 primers valors de la llista:

{
    const xs: (number| null) [] = [8, 9, 4, 5, null, 6, 2, 9, null, 4, 7, 2, 3]

    // ...

    console.log(mean) // 5.2
}

Solució imperativa

Et toca a tu

Solució funcional

{
    const xs: (number| null) [] = [8, 9, 4, 5, null, 6, 2, 9, null, 4, 7, 2, 3]

    const mean = xs.slice(0,5).filter(x => x!= null).reduce((acc,x)=> acc + x) / 5
    
    console.log(mean) // 5.2
}

2.- Calcula la mitjana aritmètica dels 5 primers números de la llista (has d'ometre els valors null):

{
    const xs: (number| null) [] = [8, 9, 4, 5, null, 6, 2, 9, null, 4, 7, 2, 3]

    // ...
    
    console.log(mean) // 5.2
}

Solució imperativa

Et toca a tu

Solució funcional

{
    const xs: (number| null) [] = [8, 9, 4, 5, null, 6, 2, 9, null, 4, 7, 2, 3]

    const mean = xs.filter(x => x!= null).slice(0,5).reduce((acc,x)=> acc + x) / 5
    
    console.log(mean) // 6.4
}