Salta el contingut

UD6. Arrays en Java i Python

Introducció

Tots els tipus de dades que hem vist fins ara són tipus bàsics (també anomenats simples, atòmics o elementals). Es caracteritzen perquè les variables d'eixos tipus només poden guardar un únic valor en cada moment.

Ara vorem com guardar molts valors en una sola variable. Eixa variable serà d'un tipus de dades compost.

representació d'un vector

Per a què serveixen estos tipus de dades?

Imaginem que volem un programa que demana les notes de 100 alumnes i després en modifique una en concret.

Amb variables simples, el programa seria molt farragós:

Java
double nota1, nota2, ..., nota100;
int alu;
double novaNota;

nota1 = funcionsIO.readDoubleC("Nota de l'alumne 1");
nota2 = funcionsIO.readDoubleC("Nota de l'alumne 2");
...
nota100 = funcionsIO.readDoubleC("Nota de l'alumne 100");

alu = funcionsIO.readIntC("Dis-me un alumne per a canviar nota");
novaNota = funcionsIO.readDoubleC("Quina nota vols posar-li?");

switch(alu){
    case1: nota1 = novaNota; break;
    case2: nota2 = novaNota; break;
    ...
    case3: nota3 = novaNota; break;
}

En canvi, usant variables compostes el programa seria més fàcil i curt:

Java
double notes[] = new double[100]; //(1)!
int alu;
double novaNota;

for (alu = 0; alu < notes.lenght; alu++){
    notes[alu] = funcionsIO.readDoubleC("Nota de l'alumne " + alu);
}

alu = funcionsIO.readIntC("Dis-me un alumne per a canviar la nota");
novaNota = funcionsIO.readDoubleC("Quina nota vols posar-li?");

notes[alu] = novaNota;
  1. Si foren més alumnes, simplement caldria canviar este número.

Usant variables simples encara es complicaria més si férem altres operacions amb les moltes notes, com calcular la màxima, la mínim, la mitja, ordenar-les...

Amb este exemple hem introduït les variables compostes, però vorem en detall com crear-les, com introduir valors en elles, com accedir a eixos valors, etc.

Hi ha molts tipus de dades compostes. Alguns són:

  • Arrays
    • D'1 dimensió: vectors
    • De 2 dimensions: matrius
    • De 3 dimensions: arrays tridimensionals
  • Cadenes: per a textos
  • Llistes: grandària ampliable i amb moltes utilitats
  • Objectes: per a guardar dades de distints tipus

Vectors en Java

Definició de vector

Conjunt finit d'elements del mateix tipus, als quals podem accedir mitjançant el nom del vector i un índex (posició dins del vector).

Com hem dit abans, un vector és un array d'1 dimensió. Per exemple, el lloc on podem guardar les notes de 100 alumnes.

La forma general de declarar un vector és:

tipusDeDades[] nomVector = new tipusDeDades[dimensió];

  • tipusDeDades: un dels tipus simples coneguts (int, char, boolean, float, double...) o bé una classe(ja ho veurem) com String, etc.
  • dimensió: Quantitat d'elements que tindrà el vector.

Estem fent dues coses: declarant el vector i assignant-li memòria. Ja vorem que a vegades convé separar estes dos coses. En eixos casos ho farem així:

Java
...
tipusDeDades[] nomVector; //(1)!
...
nomVector = new tipusDeDades[dimensió]; //(2)!
...


...

nomVector = new tipusDeDades[dimensió]; //(3)!
  1. Declarem el vector.
  2. Li assignem memòria.
  3. Si tornem a assignar una nova memòria per al vector, perdrem les dades que tenia abans.

Exemple

Veiem amb este exemple les 2 formes de declarar un vector:

Java
int[] edats = new int[7]; // Declarem el vector i reservar-li memòria
int anys[] = new int[5]; //(1)! 
  1. Altre vector. Es poden posar els [corxets] davant o darrere del nom del vector quan el declarem
Java
1
2
3
int[] edats;         // Declarem el vector
....
edats = new int[7]; // Reservem memòria al vector

En Java, per defecte, els vectors d'enters s'inicialitzen a 0:

Vector d'ints

Declarar un vector amb valors inicials

Igual que es fa en les variables simples, podem donar valors inicials en el moment de declarar-lo. EN este cas no s'indica la dimensió del vector, sinó que el vector tindrà tants elements com valors indicats:

Java
int dies[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int edats[] = new int[]{19, 17, 23, 20, 19, 18, 20} //(1)!
  1. Podem fer-ho d'eixes dos formes: amb el new int[], i sense.

Però si volem donar un conjunt de dades després de la declaració, només així:

Java
1
2
3
int edats[];
// edats = {19, 17, 23, 20, 19, 18, 20}; <-- ERROR DE COMPILACIÓ!
edats = new int[]{19, 17, 23, 20, 19, 18, 20};

Tractament de cada element del vector

Cada element del vector es pot tractar com una variable simple. Per a accedir a cada element del vector, ho farem amb el nom del vector i l'índex corresponent tancat entre claudàtors:

Accés a element d'un vector amb índex

Com ja hem dit, cada element del vector es pot tractar com una variable simple. Per tant, vegem amb exemples què podem fer amb cada element del vector:

  • Assignar un valor a un element del vector:
Java
edats[3] = 7;                                       // Assignem un valor directament
edats[4] = funcionsIO.readIntC("Quina edat té la 5a persona?"); // Assignem un valor des de teclat
  • Consultar el valor d'un element del vector:
Java
1
2
3
System.out.println(edats[3]);   // Mostrem el valor per pantalla
edatPep = edats[4];             // Copiem el valor a altra variable
if(edats[4] < 18) ...            // Utilitzem el valor en una expressió

L'Índex de l'element d'un vector

L'índex és la posició de cada element del vector. Recordem que, per exemple, amb l'index 3 podrem accedir a la 4a posició del vector (ja que la primera posició és la 0).

Què pot ser un Índex?

L'índex del vector és un enter. Podrà ser una constant, variable o expressió, però entera:

Java
1
2
3
4
...
numPersona = funcionsIO.readIntC("De quina persona vols saber l'edat (de l'1 al 7)?");
System.out.println("La persona" + numPersona + " té " + edats[numPersona-1] + " anys."); //(1)!
...
  1. Ací l'índex és l'expressio numPersona-1. El -1 és perquè si un array té 7 elements, estos queden indexats del 0 al 6. Per això, si vull accedir al 3r element, hauré de fer-ho posant un 2 a l'índex.

En este cas, si per teclat es contesta, per exemple, un 9, el programa avostaria degut a l'error ArrayIndexOutOfBoundsException. Vegem per què:

Límits de l'índex

El mínim índex que podem posar en un vector és el 0. El màxim índex és un menys que la dimensió del vector. Si accedim a una posició d'un vector fora dels seus límits donarà error quan s'execute el programa ja que estarem accedint a una zona de memòria no reservada per al vector. És més: eixa zona de memòria podria estar reservada per a altra variable.

Java
1
2
3
4
5
6
7
8
int edats[] = new int[7]; //(1)!
...
edats[0] = 10;
edats[6] = 18;

edats[7] = 10;  // ERROR (2)
edats[8] = 9;   // ERROR
edats[-1] = 10; // ERROR (3)
  1. Podrem accedir a les posicions 0 a 6 del vector
  2. Qualsevol d'eixes intruccions donaria l'error d'execució ArrayIndexOutOfBoundsException
  3. En Python amb el -1 accedirem a l'última posició, però en Java dona ERROR!

Recorregut d'un vector

Recorregut d'un vector

Imaginem que un vector té 1000 posicions i volem mostrar-les totes. Com ho fem?

Java
String noms[] = new String[1000];
...

Ja vorem per què NO podem fer-ho amb un únic println del nom del vector. Per tant, haurem de recórrer tots els seus components, amb un bucle. Tenim 2 opcions:

a. Recórrer el vector amb un for tradicional:

Recorregut d'un vector

Java
1
2
3
for(int i = 0; i < noms.length; i++){
    System.out.println(noms[i]);
}
  • L'índex del vector és una variable entera (en este cas i) que anirà agafant tots els possibles valors de les posicions del vector (0, 1, 2 ... 999).
  • En compte de posar 1000, usarem sempre la propietat length del vector (nomVector.length). Així, si després el programador canvia eixe 1000 per altre número, no ho ha de canviar en altres parts del programa.

b. Recórrer el vector amb un for tipus foreach:

Recorregut vector amb foreach

Java
1
2
3
for (String nom: noms){
    System.out.println(nom);
}
  • Este tipus de bucle serveix per a recórrer llistes (arrays, etc) quan no ens faça falta accedir a les posicions de cada element.
  • Farà tantes passades com elements tinga el vector.
  • En cada passada, en la variable nom (del mateix tipus que el contingut del vector) s'anirà copiant el contingut de cada posició.
  • Amb esta forma no podem modificar els elements del vector. Només consultar-los.

Els noms de vector i els noms dels índex

Suposem que tenim un vector per guardar les notes dels alumnes:

  • El nom del vector sol ser plural, ja que guarda molts valors. En este exemple el nom del vector és notes i no nota. A més ha de tindre un nom significatiu: notes. No és convenient dir-li vector1, ni dades, etc.
Java
double notes[] = new double[50];
  • El nom de l'índex del for sol ser la variable i però a vegades convé posar un nom més significatiu. Podria ser nota? No, ja que eixa variable no guardarà la nota d'un alumne, sinó una posició d'un alumne, un identificador de l'alumne. Podríem dir-li, per exemple, alumne, ja que tindrem l'alumne 0, l'alumne 1 ... i l'alumne 49.
Java
1
2
3
for (int alumne = 0; alumne < notes.length; alumne++){
    System.out.println(notes[alumne]);
}
  • El nom de la variable del foreach convé que es diga igual que el vector però en singular, ja que el contingut de la variable serà el contingut de cada element del vector.
Java
1
2
3
for (double nota: notes){
    System.out.println(nota);
}

Inicialització d'un vector

Recordem que un vector el declarem així:

Java
int edats[] = new int[7];

Aixpo posa un 0 en cada component. Si el vector fora de booleans, cada element tindria un false, etc. I si volem que inicialment tinguen un altre valor? Podem fer-ho de distintes formes:

a. Indicant els distints valors (ja ho hem vist)

En el moment de la creació:

Java
int edats[] = {18, 17, 20, 22, 20}; // Per tant, el vextor serà de dimensió 5

En altre moment:

Java
int edats[];
edats = new int[]{18, 17, 20, 22, 20}; // Així també es pot fer en la declaració

b. Recorrent el vector amb un bucle que faça assignacions

Igual que abans hem usat un for per a mostrar tots els elements del vector, també podem usar un for per a assignar un valor a cada element:

Java
1
2
3
4
5
int edats[] = new int[7];

for (int i = 0; i < edats.length; i++){ //(1)!
    edats[i] = 18; // O bé: edats[i] = funcionsIO.readIntC("Dis-me edat de l'alumne " + (i+1));
}
  1. Recorda usar el .length (no el 7)

Compte amb el foreach

No ho podem fer amb un foreach perquè ENS FALTARIA L'ÍNDEX!.

Representació gràfica d'un vector

Davant d'un problema sobre vectors, hem de plantejar-nos el dibuixet del vector amb les variables que li afecten.

Per exemple, volem guardar les notes de 25 alumnes. Suposant estes definicions:

Java
1
2
3
4
final int QALU = 25;    // Quantitat d'alumnes (majúscules)
...
double notes[QALU];     // Variable composta per a guardar les notes de 25 alumnes
int alu;                // Índex (minúscules). Cada volta guardarà el número d'un alumne

... faríem la següent representació gràfica:

Representaciño gràfica d'un vectr

I a partir del dibuix és més fàcil fer el codi per a guardar totes les notes del vector:

Java
1
2
3
for (int alu = 0; alu < notes.legth; alu++){
    notes[alu] = funcionsIO.readDoubleC("Dis-me la nota de l'alumne " + alu);
}
Exercici 1. Vectors en Java

CONSELL: Abans de fer exercicis sobre vectors, fes el dibuixet del vector (o vectors) posant l'índex, nom de vector, grandrària... (com a l'apartat anterior).

Fes un programa que faça el següent:

a. Crear un array de nom edats, de qAlu elements de tipus enter, per a guardar les edats de qAlu alumnes. S'ha de demanar la variable qAlu a l'usuari.

b. Omplir el vector demanant les dades per teclat.

c. Demanar un número d'alumne i mostrar la seua edat. El número d'alumne serà la posició dels elements (0 a 9). No ha de donar error si s'introdueix un número incorrecte.

d. Mostrar quants alumnes són menors d'edat.

e. Mostrar l'edat mínima dels alumnes i a quin número d'alumne correspon. Si són molts alumnes que tenen la mínim edat, mostra el primer que aparega.

f. Posar en altre vector de nom majors aquells números d'alumnes que són majors d'edat.

g. Recórrer el vector majors per a mostrar els números d'eixos alumnes i les edats corresponents.

Vectors paral·lels

Suposem que volem guardar les notes (double) de 10 alumnes i els respectius números d'expediants (int). Per a això necessitariem un vector de 10 números amb decimals per a guardar les notes i una altre vector de 10 números enters per a guardar els números d'expedients.

fila de persones

notes [8.0][9.3][5.6][7.3][7.0][5.4][6.7][4.2][3.8][9.4] expedients [133][137][139][138][136][130][140][142][131][134]

L'alumna que figura a la posició número 2 (0, 1 i 2) ha tret de nota un 5.6 i té el número d'expedient 139

Eixos 2 vectors diem que són paral·lels ja que tenen la mateixa quantitat d'elements, i en la mateixa posició de cada vector guarda informació del mateix objecte (en este cas, del mateix alumne).

AVANTATGE: un únic bucle per a recórrer diversos vectors paral·lels.

Java
1
2
3
4
5
final int Q_ALUMNES = 10;
...
for (int alu = 0; alu < Q_ALUMNES; alu ++){
    System.out.println("Alume núm. " + alu + " Exp: " + expedients[alu] + " Nota: " + notes[alu]);
}
Exercici 2. Vectors paral·lels

Fes un programa en Java que demane el número d'expedient, nota i edat de 15 alumnes (amb un únic bucle). Posteriorment, que mostre en 3 columnes les 3 dades de cada alumne. Després, es demanarà per teclat un número d'expedient i es mostrarà per pantalla la seua edat i nota.

Tractament de tot el vector en conjunt

Abans de vore les operacions que podem fer en un vector en conjunt (no component a component), hem de tindre en compte que si usem el vector sense indicar la posició, estem accedint a una adreça de memòria RAM (on comencen les dades que guarda el vector).

Exemple

Suposem que tenim estos dos vectors:

Java
int notesPep[] = {5, 7, 6};
int notesPepa[] = {7, 8, 8};

i pososem que, quan s'ha executat el programa, se'ls han assignat estes zones de memòria RAM (que comencen en la 1004 i en la 1024):

RAM i vectors

A la vista d'este esquema, quan usem el nom d'un vector sense indicar l'índex (ni els claudàtros, clar), estarem accedint a eixe número 1004 o 1024, no al contingut del vector.

Per tant, hem d'anar en compte amb les operacions que fem amb els vectors sencers en conjunt, ja que, possiblement, no estarem fent allò que pretenem. Ara ho vorem.

Copiar vectors

Què pasa si copiem un vector a un altre?

Java
1
2
3
4
5
int notesPep[] = {5, 7, 6};
int notesPepa[] = {7, 8, 8};
...
notesPepa = notesPep; //(1)!
...
  1. No donarà error però està fent que notesPepa apunte a la mateixa adreça que notesPep

Efectivament, si mostrem ara les notes de Pepa, vorem que sí que mostra 5, 7, 6 (en compte de 7, 8, 8 que tenia abans), però... compte! Si modifiquem una nota de Pep, també estarem modificant la de Pepa, i al revés.

SOLUCIÓ: Si realment volíem que notesPepa tinguera els mateixos valors que notesPep (conservant l'adreça de memòria que tenia) caldria copiar component a component, mitjançant un bucle. Vorem després com fer-ho.

Comparar vectors

Què passa si comparem vectors?

No es compararan els seus valors sinó l'adreça de memòria que ocupen. Per tant:

Java
int notesPep[] = {5, 7, 6};
int notespepa[] = {5, 7, 6}; //(1)!

if (notesPep == notesPepa){ //(2)!
    ...
}

notesPepa = notesPep; //(3)!
notesPepa[1] = 10; //(4)!

if (notesPep == notesPepa){ //(5)!
    ...
}
  1. Els 2 vectors tenen els mateixos valors però en distinta zona de memòria.
  2. Donarà false ja que, encara que tinguen els mateixos valors, l'adreça de memòria és distinta.
  3. Els 2 vectors apunten a la mateixa zona de memòria.
  4. Estem canviant una nota de Pepa... i de Pep!
  5. Donarà true ja que l'adreça de memòria és la mateixa.

Altres operacions

No podem mostrar "de colp" un vector ni assignar-li un valor a tots els components:

Java
1
2
3
int notesPep[] = {5, 7, 6};
System.out.println(notesPep); //(1)!
notesPep = 7; //(2)!
  1. No donarà error de compilació ni d'execució però mostrarà l'adreça de memòria RAM on comença el vector (un número en hexadecimal).
  2. Error de compilació.

SOLUCIÓ: tant per mostrar els elements d'un vector, com per assignar un mateix valor a cada element, cal fer-ho mitjançant un bucle.

Exercici 3. Operacions amb vectors en conjunt

a. Crea 3 vectors d'enters (v1, v2 i v3) sense reservar memòria (sense indicar la grandària ni posar valors inicials).

b. Pregunta per teclat quantes dades es volen guardar en els vectors (només 1 quantitat, igual per als tres).

c. Reserva memòria al vector1 amb eixa quantitat d'elements introduïda.

d. Ompli v1 amb dades introduïdes per teclat.

e. Copia el vector v1 al vector v2, en una sola operació.

f. Copia el vector v1 al vector v3, copiant component a component. Primer caldrà reservar memòria per a v3.

g. Mostra per pantalla si v1 és igual a v2, en una sola operació. Fes el mateix per a v1 i v3.

h. Mostra per pantalla si v1 és igual a v3, component a component (però només haurà de dir: "vectors iguals" o "vectors diferents").

i. Mostra el que hi ha en cada posició de cada vector (format lliure).

j. Fes que els 3 vectors ara tinguen 5 dades cadascun. I que totes les dades tinguen el valor -1. Torna a mostrar el contingut dels vectors.

k. Pensa quin resultat de mostrar per pantalla i comprova el resultat després d'executar el programa.

Vectors en Python (llistes)

Els vectors de Python també s'anomenen llistes. Ara bé, les llistes de Python:

  • Poden contindre elements de tipus diferents.
  • Són dinàmiques: poden canviar de grandària al llarg del programa.

Creació d'una llista

Recordem que en Python no es declaren les variables. Tampoc els vectors. Per tant, per a crear un vector, simplement hem d'inicialitzar-lo. Vegem 2 formes de fer-ho:

a) Creació d'una llista indicant els valors

Python
# Llista d'enters:
notes = [7, 9, 8, 7]

# Llista de textos:
noms = ["pep", "pepa", "pepeta", "pepet"]

# Llista amb tipus de dades diferents:
persona = ["Pep", "Garcia", 50, 72.5]

# Llista buida i anem afegint valors:
llista = []
llista.append("Pep")
llista.append("Garcia")

# Llista de 4 elements sense valors:
llista = [None, None, None, None]

b) Creació d'una llista indicant la grandària

Python
1
2
3
4
5
6
7
8
# Llista de 7 elements enters iniciats a 3
vides = [3]*7   # [3, 3, 3, 3, 3, 3, 3]

# Llista de 10 caràcters amb valors alternats 'a' i 'b':
lletres = ['a', 'b']*5  # ['a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b']

# Llista de 5 elements sense valors
coses = [None]*5    # [None, None, None, None, None]

Tractament de cada element de la llista

Com en C i Java: amb el nom del vector i l'índex entre claudàtors.

Python
1
2
3
4
coses[3] = 6
vides[5] = vides[5] - 1
print(notes[i])
print(notes[-1]) #(1)!
  1. Python admet índexs negatius: amb el -1 accedim a l'últim element de la llista. Amb el -2 accedim al penúltim. I així, successivament.

Recorregut d'una llista

coses = [1984, "Paco Garcia", "1DAM-SP", "PRG", "SXA", True, 15.5]

Si volem recórrer eixa llista (per a mostrar els elements, etc.), igual que en Java, en Python també hem d'utilitzar un bucle, preferiblement, un for. Però recordem que el for de Python no és com el de Java. Veiem 2 formes de recòrrer la llista:

a) Amb un bucle for tradicional: accedint amb l'índex dels elements

Podem recórrer-la amb les posicions que van de la 0 a la longitud de la llista -1:

Python
for i in range (0, len(coses)): # És com si férem: for i in [0,1,2,3,4,5,6]
    print("L'element de la posició", i, "val", coses[i])

O bé, sense indicar la posició inicial (ja que per defecte és 0):

Python
for i in range(len(coses)): # És com si férem: for i in [0,1,2,3,4,5,6]
    print("L'element de la posició", i, "val", coses[i])

NOTES

  • len(llista) ens dona la longitud de la llista.
  • Recordem que amb range(10,20) obtenim els números del 10 al 19. I que amb range(20) obtenim els números del 0 al 19.
  • Per tant, amb range(len(llista)) obtenim totes les posicions de la llista.

b) Amb un for tipus foreach: accedint directament als elements

Python
for element in coses:
    print("Un element val", element)

Però en este cas no podem accedir al número de la posició de cada element, ni podem modificar la llista. Per tant, usarem esta forma quan no ens faça falta saber les posicions de cada element ni hajam de modificar la llista.

Tractament de tota la llista en conjunt

En Python, igual que en Java, si usem el vector sense indicar la posició, estem accedint a una adreça de memòria RAM (on comencen les dades que guarda el vector). Recordem:

Python
notesPep = [5, 7, 6]
notesPepa = [7, 8, 8]

Els vectors a la RAM

Per tant, passarà igual que a Java:

  • Si copiem un vector a un altre, els 2 vectors apuntaran a la mateixa zona de memòria. Llavors, si canviem algun element canviarà als 2 vectors.
  • Si li assignem altre conjunt de valors també estarem assignant una nova zona de memòria i, per tant, perdrem les dades que tenia abans.
Python
1
2
3
notes = [5]*10      # Ara notes val [5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
...
notes = [6, 7, 9]   # Ara notes val [6, 7, 9]

Però, a diferència de Java:

  • Si comparem un vector amb altre, encara que tinguen distinta zona de memòria, si els elements són iguals donarà True.
Python
1
2
3
v1 = [10, 20, 30]
v2 = [10, 20, 30]
print(v1 == v2)     # Mostrarà True
  • Podem mostrar "de colp" tot un vector:
Python
print(notesPep)     # Mostrarà tot el vector, en este format: [5, 7, 8]
Exercici 4. Vectors en Python

Fes en Python els exercicis de vectors que has fet en Java 😉

Matrius en Java

Són com els vectors que hem vist, però en 2 dimensions (arrays bidimensionals). També poden haver *arrays de 3 dimensions, de 4...

Arrays multidimensionals

S'utilitzen per a guardar moltes dades, del mateix tipus, quan cadascuna d'eixes dades es pot identificar per dos (o més) índexos. Per exemple:

  • Les notes dels alumnes en distintes avaluacions:

matriu amb notes i avaluacions

  • Els taulers de jocs:

Taulers de jocs en forma de matriu

  • Una imatge .bmp o .jpg es guarda internament com una matriu de 3 dimensions. Cada element representa un píxel de la foto, i està indexat per una posició de la foto (alt, ample) i per un valor depenent del color (roig, verd o blau).

imatge matricial

Per exemple, suposant que el verd és la posició 2, si volem que el píxel 150,300 tinga una tonalitat de 10 verd, podríem fer: foto[150][300][2] = 10;

Declaració de matrius en Java

Podem definir una matriu com un conjunt finit d'elements del mateix tipus, als quals podem accedir mitjançant el nom de la matriu i dos índexs.

Exemple de declaració d'una matriu

Java
1
2
3
4
5
final int ALU = 6                       // Quantitat d'alumnes
final int EXER = 5                      // Quantitat d'exercicis
float notes[][] = new float[ALU][EXER]; // Guardarà 30 notes (6*5) (1)!
int alu;                                // Índex per a recórrer els alumnes
int exer;                               // Índex per a recórrer els exercicis
  1. O bé [EXER][ALU], però la disposició que triem s'ha de respectar en tot el programa.

Representació d'una matriu

Una matriu és un vector de vectors

També podem definir una matriu com un vector on cadascun dels seus elements és un altre vector.

Veiem-ho amb l'exemple anterior, on volem guarar les notes que han tret 6 alumnes en cadascun dels 5 exercicis.

Java
1
2
3
final int ALU = 6;                      // Quantitat d'alumnes
final int EXER = 5;                     // Quantitat d'exercicis 
float notes[][] = new float[ALU][EXER]; // Per a guardar 30 notes

En el següent gràfic (part esquerre) veiem que, per a guardar les notes dels 6 alumnes tenim el vector de notes. El que passa és que cada alumne no té una nota, sinó 5. És a dir, en cada posició del vector de notes, hi ha un altre "vectoret".

vector de vectors

En el gràfic (part dreta) veiem que eixa estructura de vector de vectors és realment una matriu. Aleshores, tenim que:

  • notes: és tota la matriu (les notes de tots els alumnes en tots els exercicis).
  • notes[2]: és un vector de notes (les notes de l'alumne 2).
  • notes[4][3]: és un element nota (la nota de l'alumne 4 a l'exercici 3).

Inicialització de matrius

Ja hem vist que, igual que en els vectors, les matrius es declaren així:

tipusDeDades nomMatriu[][] = new tipusDeDades[qFiles][qColumnes];

O bé, igual que en els vectors, podem separar la part de la reserva de memòria:

Java
1
2
3
tipusDeDades nomMatriu[][]; //(1)!
...
nomMatriu = new tipusDeDades[qFiles][qColumnes]; //(2)!
  1. Declarem la matriu
  2. Li assignem memòria

Igual que en els vectors, en compte de la reserva de memòria, es poden donar uns valors inicials als elements de la mtriu.

Per exemple, si volem que tinga estos valors:

10 20 30
40 50 60

Farem el següent:

Java
int matriu[][]={{10, 20, 30}, {40, 50, 60}}; //(1)!
  1. Cada "grupet de números" és la inicialització de cada vector de la matriu. Per tant, hauran de ser de la mateixa grandària.

La propietat length en les matrius

Suposem que tenim esta matriu:

Java
float m[][]=new float[6][5];
  • Amb m.length tindrem eixe 6 (quantitat de files)
  • Amb m[0].length tindrem eixe 5 (quantitat de columnes)

Ja vorem que, en ocasions, en alguna part del programa no sabrem la quantitat de files i columnes que té eixa matriu m (no coneixerem eixe 6 i 5). En eixos casos accedirem amb m.length per a accedir a la grandària de la 1a component de la matriu, i amb m[0].length per a accedir a la grandària de la 2a component de la matriu. Però per què?

Recordem que una matriu és un "vectorot" de "vectorets". Per tant, m.length és la longitud d'eixe "vectorot". I com m[0] és el primer dels "vectorets", m[0].length és la longitud d'eixe "vectoret" (i dels altres, ja que tots són igual de grans). Sabent això, també podrem accedir als "cantons" de la matriu, etc. És a dir:

Esquema de matriu amb lengths

Recorreguts d'una matriu

Si volem mostrar tots els elements d'una matriu, o assignar-los un valor, etc., haurem de recòrrer-la tota. És a dir, haurem de passar per cadascun dels seus elements. Podem fer eixe recorregut de 2 maneres: per files o per columnes.

Recorregut per files:

Recorregut per files

Recorregut per columnes:

Recorregut per columnes

Però si només volem recórrer una fila, per exemple la 2, NO hem de recórrer tota la matriu, sinó simplement la fila que volem:

Recorregut d'una fila en una matriu

I si volem recórrer només una columna, per exemple la 1, farem:

Recorregut d'una columna en una matriu

Un error freqüent és que, per a recórrer una columna (per exemple la 1), es recórrega tota la matriu:

Error freqüent

Exercici 5 RESOLT

Estadística de temperatures

A un centre meteorològic volem guardar les temperatures d'un mes (31 dies), mesurades 4 voltes al dia (a les 0, 6, 12 i 18 hores de cada dia).

Al principi del programa es demanaran totes les temperatures del mes: per cada dia es demanaran les 4 temperatures.

posteriorment, el programa presentarà un menú perquè l'usuari faça una anàlisi de les dades recol·lectades:

Text Only
1
2
3
4
1. Temperatura mitja d'un dia demanat per programa.
2. Temperatura mitja d'una hora demanada per programa.
3. Temperatura mitja del mes.
0. Eixir.

Repetidament es mostrarà el menú, es demanarà una opció i s'executarà, fins posar l'opció 0.

Plantejament de la solució

Caldrà guardar les dades en una matriu. Podem plantejar-ho de moltes formes. Per a vore l'estructura de dades que ens farà falta, hem de fer-nos un "dibuxet" amb el que volem. Així veiem que ens vindria bé una matriu de 32 x 4:

Dibuixet plantejament exercici

(*) Si definiríem una matriu de 31 files, els números de fila anirien de 0 a 30 però els dies són de l'1 al 31. Per tant, definiriem una matriu de 32 files, i només usarem de la fila 1 a la 31. Simplement, no usarem la fila 0.

Java
public class ExerciciTemperatures{
    public static void main (String args[]){

        // DECLARACIÓ DE VARIABLES ------------------------------
        final int DIES = 3;
        final int FRANGES = 4;

        int temp[][] = new int[DIES+1][FRANGES];

        int diaTriat, horaTriada, franjaTriada;
        int opcio;
        float total, mitjana;

        // INTRODUCCIÓ DE DADES ---------------------------------
        System.out.println("--- INTRODUCCIÓ DE TEMPERATURES ---");

        for (int dia = 1; dia <= DIES; dia++){  // No agafem el dia 0
            System.out.println("\nDia " + dia);

            for (int franja = 0; franja < FRANGES; franja++){
                temp[dia][franja] = funcionsIO.readIntC("Temperatura a les " + (franja * 6) + ": ");
            }
        }

        // MOSTREM LES TEMPERATURES POSADES ---------------------

        // Mostrem el titolet de les hores
        for(int franja = 0; franja < FRANGES; franja++){
            System.out.print("\t" + (franja * 6) + "h");
        }
        System.out.println("");

        // Mostrem les files de la matriu
        for(int dia = 1; dia <= DIES; dia++){
            System.out.print("Dia_" + dia + "\t");

            for(int franja = 0; franja < FRANGES; franja++){
                System.out.print(temp[dia][franja] + "\t");
            }

            System.out.println("");
        }

        // BUCLE: Mostrar menú, demanar opció i executar opció
        do{
            // MOSTREM MENU
            System.out.println("***********************************");
            System.out.println("1. Mostrar temp. mitjana d'un dia");
            System.out.println("2. Mostrar temp. mitjana d'una hora");
            System.out.println("3. Mostrar temp. mitjana del mes");
            System.out.println("0. Eixir");
            System.out.println("***********************************");

            // DEMANEM UNA OPCIO CORRECTA
            do{
                opcio = funcionsIO.readIntC("Tria opció: ");
            } while ((opcio < 0) || (opcio > 3));

            // EXECUTEM L'OPCIÓ TRIADA
            switch(opcio){
                case 1: // Mitjana de les temperatures d'un dia
                    do{
                        diaTriat = funcionsIO.readIntC("De quin dia vols la mitjana: ");
                    } while ((diaTriat <= 0)||(diaTriat > DIES));

                    total = 0;
                    for(int franja = 0; franja < FRANGES; franja++){
                        total = total + temp[diaTriat][franja];
                    }
                    mitjana = total / FRANGES;
                    System.out.println("La mitjana del dia " + diaTriat + " és " + mitjana);
                    break;

                case 2: // Mitjana de les temperatures d'una hora
                    do{
                        horaTriada = funcionsIO.readIntC("De quina hora vols la mitjana (0, 6, 12, o 18): ");
                        franjaTriada = horaTriada / 6;
                    } while (franjaTriada < 0 || franjaTriada > 3);

                    total = 0;
                    for(int dia = 1; dia <= DIES; dia++){
                        total = total + temp[dia][franjaTriada];
                    }
                    mitjana = total / DIES;
                    System.out.println("La mitjana de les " + (franjaTriada * 6) + " és " + mitjana);
                    break;

                case 3: // Mitjana de les temperatures de tot el mes
                    total = 0;
                    for(int dia = 1; dia <= DIES; dia++){
                        for(int franja = 0; franja < FRANGES; franja++){
                            total += temp[dia][franja];
                        }
                    }
                    mitjana = total / (DIES * FRANGES);
                    System.out.println("La mitjana del mes és " + mitjana);
                    break;

                case 0: // Eixir
                    System.out.println("Adéu!");
                    break;

                default:
                    System.out.println("Opció incorrecta");

            } // Fi del switch
        } while (opcio != 0); //Fi del bucle
    }
}
Exercici 6. Matrius en Java

Modifica l'exercici anterior sobre l'estadística de temperatures, afegint estes opcions al menú:

  • 4.Mostra temperatura en un dia i hora en concret.
  • 5.Mostra la mínima i la màxima d'un dia.
  • 6.Canviar una temperatura.

Pensa altres possibles opcions que podries fer i implementa-les.

Exercici 7

Fes un programa que guarde en una matriu les notes de programació que han tret 15 alumnes en cadascuna de les 3 avaluacions. A continuació trau de cada alumne: el número (1 a 15), la nota mitjana i quantes suspeses. També trau de cada avaluació: el número (1 a 3), la nota màxima i la mínima. Per exemple, l'eixida de resultats podria ser:

Exemple de sortida
ALUMNE   MITJA   SUSPESES
 1       3.33     3
 2       5.00     1
 3       6.67     0
 4       8.76     0
...

AVAL   MÍNIMA   MÀXIMA
 1      3.5      5.7
 2      3.0      8.0
 3      4.0      9.0
Exercici 8

Modifica el programa anterior perquè es puguen guardar, en la mateixa matriu (ara serà tridimensional), a més de les notes del mòdul de programació, les de bases de dades i les de llenguatge de marques. Mostra quantes avaluacions han suspés en total els alumnes.

Matrius en Python

Veiem les diferències de crear la matriu en Java i Python:

Matrius en Java i Python

Java
1
2
3
4
final int FIL = 6;
final int COL = 5;

float matriu[][] = new float[FIL][COL];
Python
1
2
3
4
5
6
FIL = 6
COL = 5

matriu = [None] * FIL
for f in range (FIL):
    matriu[F] = [0] * COL

En Java es crea directament, amb el new i indicant la quantitat de files i columnes. Però Python només entén una matriu com un vector de vectors (recorda que ho hem comentat també en el cas de Java). Per tant, en Python primer creem un vector i després fem que cada component del vector siga també un vector.

Matrius en Python

En compte d'inicialitzar els components a 0, ho haguérem pogut fer a qualsevol valor.

Ara bé: Python té una altra forma de crear matrius, encara que no massa intuïtiva:

Python
matriu = [[0]*COL for f in range(FIL)]

L'accés als elements és igual que en Java matriu[f][c]

Matriu tridimensional en Python

El procediment seria el mateix:

  • Crear un vector
  • Per a cada element d'eixe vector, convertir-lo també en vector
  • Per a cada element d'eixe nou vector, convertir-lo també en vector

Per exemple, si volem una matriu de 2 x 3 x 4:

Python
1
2
3
4
5
6
7
m = [0]*2 #(1)!

for f in range(2):
    m[f]=[0]*3 #(2)!

    for c in range (3):
        m[f][c] = [0]*4 #(3)!
  1. Creem un vector de 2 elements (2 files)
  2. Ara cada fila serà un vector de 3 elements (3 columnes)
  3. Ara cada columna d'eixa fila serà un vector de 4 elements (4 de profunditat)

Si mostrem la matriu (print(m)) vorem que tenim una matriu de 2 files x 3 columnes x 4 "de profunditat":

print(m)

Per a accedir a cada element, igual que en Java: matriu[f][c][p]

Exercici 9. Matrius en Python

Fes en Python els exercicis de matrius proposats en Java 😉

Cadenes de caràcters

Com es guarda un nom de persona, per exemple? Alguns llenguatges com C, ho guarden en un vector de caràcters. Però en Python i Java ho tracten com un tipus de dades, amb moltes operacions disponibles sobre variables d'eixe tipus.

  • Python té el tipus de dades str
  • Java té la classe String (una classe és més que un tipus, ja ho vorem)

Cadenes de Java: la classe String

Declaració de variables String

Java
1
2
3
String nom; //(1)

nom = "Pep Garcia"; //(2)
  1. Ja vorem que, més que "variables de tipus String", realment són "objectes de la classe String".
  2. En Java es tanquen entre "cometes dobles". En Python, "cometes dobles" o 'simples'.

Alguns mètodes sobre cadenes en Java

Com ja hem dit, String no és un tipus, és una classe (les classes comencen en majúscula). I, per tant, tindrà uns mètodes associats, per a treballar amb cadenes. Vegem uns exemples. Partim que tenim: String nom = "Pep Garcia"

MÈTODE DE CADENES JAVA RETORNA EXPLICACIÓ
nom.length() 10 Longitud de la cadena. En un vector seria nom.lenght (sense parèntesis).
"Hola".length() 4
nom.charAt(0) 'P' Primera lletra.
nom.charAt(4) 'G' Lletra posició 4. En un vector seria nom[4]
nom.charAt(nom.legth()-1) 'a' Última lletra.
nom.charAt(10) ERROR No existeix la posició 10 en nom.
nom.substring(4, 7) "Gar" De la posició 4 a la 6.
nom.substring(4) "Garcia" De la posició 4 al final.
nom.indexOf('a') 5 Primera posició de la 'a'.
nom.indexOf('x') -1 Si no troba la lletra.
nom.indexOf('a', 6) 9 Primera posició de la 'a' a partir de la 6.
nom.indexOf("Gar") 4 Primera posició del text "Gar"
nom.contains("Gar") true Per a saber si una cadena n'inclou altra
nom.equals("Pep Garcia") true Per a saber si 2 cadenes són iguals.
nom.equals("pep garcia") false
nom.equalseIgnoreCase("pep garcia") true Per a saber si 2 cadenes són iguals sense importar les majúscules.
nom.compareTo("Pop") núm. < 0 Pep Garcia < Pop
"Pop".compareTo(nom) núm. > 0 Pop > Pep Garcia
nom.compareTo("Pep Garcia") 0 Cadenes iguals
nom.toLowerCase() "pep garcia" A minúscules.
nom.toUpperCase() "PEP GARCIA" A majúscules.
"   Hola, Pep!   ".trim() "Hola, Pep!" Lleva espais davant i darrere.
nom.replace("Pep", "Josep") "Josep Garcia" Reemplaça subcadena.
nom.replace('a', 'A') "Pep GArciA" Reemplaça caràcter.
String s = "IES Jaume II";
String[] paraules = s.split(" ");
["IES",
"Jaume",
"II"]
Obté un vector de Strings les parts de la cadena, segons el caràcter separador (igual que en Python).
Exemple d'ús dels mètodes de les cadenes en Java
Java
public class ExempleStrings {
    public static void main(String[] args) {
        String nom = funcionsIO.readTextC("Com et diuen? ");
        System.out.println("HOLA, " + nom.toUpperCase());
        System.out.println("El teu nom té " + nom.length() + " lletres");
        char utlLletra = nom.charAt(nom.length()-1);
        if (utlLletra == 'a'){
            System.out.println("Tens nom de xica");
        }
        if (nom.equals("Pep")){
            System.out.println("També eres Josep");
        }
        if (nom.indexOf('ç') >= 0){ // O bé: nom.contains("ç")
            System.out.println("Tens nom valencià");
        }
        if (nom.compareTo("Pep") > 0){
            System.out.println("Alfabèticament vas després de Pep");
        }
        nom = nom.trim(); // Llevem espais davant i darrere
        if (nom.contains(" ")){ // Si és nom compost
            System.out.println("Nom d'usuari: " + nom.replace(' ', '_'));
            String[] noms = nom.split(" ");
            System.out.println("Tens estos " + noms.length + " noms:");
            for (String nom1 : noms){
                System.out.println(nom1);
            }
        }
    }
}

En executar-se dona la següent sortida:

sortida exemple

Cadenes de Python: la classe str

Declaració de variable str

Python
1
2
3
4
5
nom1 = "Pep"
nom2 = 'Pepa' #(1)!
nom3 = '''Estimat Sr. Pep:
Bla, bla, bla...
Tavernes, 25-12-2024''' #(2)!
  1. En Python podem usar cometes dobles o simples.
  2. Si usem 3 cometes(simples o dobles), la cadena pot ocupar diverses línies.

Algunes operacions sobre cadenes en Python

Partim que tenim: nom = "Pep Garcia"

MÈTODE CADENES PYTHON RETORNA EXPLICACIÓ
len(nom) 10 Es el nom.length() de Java.
nom[2] 'p' És el nom.charAt(2) de Java.
nom[-1] 'a' Última lletra (compte! no en Java).
nom.find('a') 5 És el nom.indexOf() de Java, però el de Java no accepta el 3r paràmetre.
nom.find('x') -1
nom.find('a', 6) 9
nom.find("Gar") 4
nom.find('a', 4, 7) 5 Busca 'a' entre les posicions 4 i 6
nom.index('a') 5 És igual que el find de Python, però si no ho troba dona error.
nom.index('x') ERROR
nom.__contains__("Pep") True És el nom.contains("Pep") de Java.
"Pep" in nom
nom.__eq__("Pep Garcia") True O bé: nom == "Pep Garcia"
nom.__gt__("Xavier") False O bé: nom > "Xavier"
nom.lower() "pep garcia" És com el nom.toLowerCase() de Java.
nom.upper() "PEP GARCIA" És com el nom.toUpperCase() de Java.
"  Hola, Pep!  ".strip() "Hola, Pep!" És com el "Hola, Pep!".trim() de Java.
nom.replace("Pep", "Josep") "Josep Garcia" Igual que en Java
s = "IES Jaume II"
paraules = s.split(" ") # s.split()
["IES",
"Jaume",
"II"]
Igual que en Java.
nom.count('a') 2 Quantes voltes està la 'a' en el nom.
nom.count("Gar") 1 Quantes voltes està "Gar" en nom.
nom.count('a', 4, 7) 1 Quantes 'a' entre posicions 4 i 6
nom.startsWith("Pep") True Igual que en Java.
nom.endsWith("ia") True Igual que en Java.
nom.isalpha() False Si només està fet d'alfabètics.
L'espai (' '), etc, no són alfabètics.
nom.isupper() False Si totes les lletres són majúscules.
nom.islower() False Si totes les lletres són minúscules.
nom.istitle() True Si tot en minúscula menys la lletra inicial de cada paraula.
"1234".isdecimal() True Si tot són números. Com també: isnumeric() i isdigit()
"-1234".isdecimal() False
"12.34".isdecimal() False
"3316FP".isalnum() True Si només hi ha lletres i números.
"    ".isspace() True Si només hi ha espais en blanc.
Exemple d'ús de cadenes en Python
Python
nom = input("Com et diuen? ")
print("HOLA,", nom.upper())
print("El teu nom té", len(nom), "lletres")
if nom.endswith('a'): # O bé: nom[-1] == 'a'
    print("Tens nom de xica")
if nom.__eq__("Pep"):
    print("També eres Josep")
if nom.__contains__("Pep"):
    print("El teu nom inclou Pep")
if nom.find('ç') >= 0:
    print("Tens nom valencià")
if nom.__gt__("Pep"):
    print("Alfabèticament vas després de Pep")
nom = nom.strip()
if nom.__contains__(' '):
    print("Nom d'usuari:", nom.replace(' ', '_'))
    noms = nom.split()
    print("Tens estos", len(noms), "noms:")
    for nom1 in noms:
        print(nom1)
Exercici 10. Cadenes de caràcters en Java

Programa en Java que demane un text per teclat. Per cada paraula hauràs de dir la seua longitud i si està en majúscules o minúscules. Després mostra la paraula més llarga i l'última paraula que apareixeria en un diccionari.

PISTA: utilitza split, etc.

Exercici 11. Cadenes de caràcters en Python

Fes el mateix que a l'exercici 10, però en Python.

Llistes dinàmiques

Els arrays que hem vist en Java són llistes estàtiques: tenen una grandària fixa que s'estableix al principi i ja no pot variar durant l'execució del programa. Té sentit que siga així per a certes utilitats, ja que el dia sempre tindrà 24 hores, els alumnes sempre tenen 3 avaluacions, un tauler d'escacs sempre és 8x8...

Però a voltes la quantitat d'elements podrà canviar. Per exemple, podem tindre en un principi20 alumnes però en poden vindre més (o anar-se'n). Per a això estan les llistes dinàmiques: tindran una grandària inicial però podran canviar durant l'execució del programa. De fet, les llistes que hem vist en Python són dinàmiques.

Hi ha diferents tipus de llistes dinàmiques o "col·leccions" de dades. Cada llenguatge de programació té les seues. Algunes de Java i Python són:

COL·LECCIONS
Llistes Conjunts Diccionaris
Els elements estan ordenats? NO NO
Els elements estan indexats? NO SÍ, per la clau
Permet elements repetits? NO NO

Col·lecions

A continuació vorem un esquema resum dels principals mètodes o operacions que es poden fer amb els diferents tipus de col·leccions de Java i Python:

MÈTODES DE LES COL·LECCIONS
Llistes Conjunts Diccionaris
Llenguatge J P J P J P
Classe ArrayList list HashSet set HashMap dict
Afegir al final .add .append - - - -
Afegir a un lloc .add .insert - - - -
Afegir a cap lloc - - .add .add put [clau]=
Modificar .set [i]= - - put [clau]=
Esborrar posició .remove .pop - - - -
Esborrar element .remove .remove .remove .remove
.discard
.remove(clau) .pop(clau)
Buidar .clear .clear .clear .clear .clear .clear
Consultar posició .get [i] - - .get(clau) .get(clau)
[clau]
Saber si està un element .contains
.indexof
in
.index
.contains in .containsKey
.containsValue
in
Longitud .size len .size .size .size .size
Ordenar Collections.sort .sort - - - -
Altres .union
.intersection
.difference
.issubset
.issuperset
.values
.keyset
.values()
.keys()
.items()

A continunació vorem en detall les col·leccions que més s'utilitzen: les llistes. Java usa la classe ArrayList; Python, la classe list.

Llistes en Java: la classe ArrayList

Un ArrayList és una llista en Java. La diferència entre un vector i una llista és que la grandària d'un vector no es pot modificar i la d'una llista, sí. A més, es poden fer moltes més coses en una llista. Ara vorem com fer tot això en Java, amb exemples:

Exemples d'ús de llistes en Java
Java
import java.util.ArrayList; //(1)!
import java.util.Collections;

public class ProvesLlistes {
    public static void main(String[] args) {
        ArrayList<String> amics = new ArrayList(); //(2)!

        // AFEGIR
        amics.add("Pep");
        amics.add("Pepa"); //(3)!
        amics.add("Pepet");
        amics.add(1, "Pepeta"); //(4)!

        // CONSULTAR
        System.out.println(amics.get(0)); //(5)!
        String amiguet = amics.get(2);
        System.out.println(amics.contains("Pepa")); //(6)!
        System.out.println(amics.indexOf("Pepa")); //(7)!
        System.out.println(amics.indexOf("Josep")); //(8)!
        System.out.println(amics.size()); //(9)!
        System.out.println(amics); //(10)!

        // RECÓRRER
        for (int i = 0; i < amics.size(); i++) { //(11)!
            System.out.println(amics.get(i));
        }
        for (String amic : amics){ //(12)!
            System.out.println(amic);
        }

        // MODIFICAR
        amics.set(1, "Pau"); //(13)!

        // ORDENAR
        Collections.sort(amics); //(14)!

        // ESBORRAR
        amics.remove(1); //(15)!
        amics.remove("Pepet"); //(16)!
        amics.clear(); //(17)!
    }
}
  1. Cal importar eixa classe Arrayist
  2. Creem una llista d'amics.
  3. Afegim elements al final: ["Pep", "Pepa", "Pepet"]
  4. Afegim en la 2a posició: ["Pep", "Pepeta", "Pepa", "Pepet"]
  5. Consultem el 1r element ("Pep")
  6. Comprovem si està Pepa: true
  7. Posició on està Pepa: 2
  8. Posició on està Josep: -1
  9. Consultem la grandària de la llista: 4
  10. Mostrem la llista "de colp": [Pep, Pepeta, Pepa, Pepet]
  11. Recorrem la llista amb un for tradicional
  12. Recorrem la llista amb un bucle foreach
  13. Modifiquem el 2n element: ["Pep", "Pau", "Pepa", "Pepet"]
  14. Ordenem la llista: ["Pau", "Pep", "Pepa", "Pepet"]
  15. Esborrem el 2n element: ["Pau", "Pepa", "Pepet"]
  16. Esborrem l'element Pepet: ["Pau", "Pepa"]
  17. Esborrem la llista: []

Per practicar més...

En www.w3schools.com podem consultar i practicar l'ArrayList (llistes) i altres tipus de col·leccions, com els HashSet, els HashMap (diccionaris), etc.

Llistes de Python: la classe list

Una list és una llista en Python. Recordem que els vectors de Python són realment llistes. Per tant, ja hem vist les llistes de Python, però anem a vore altres operacions que es poden feer sobre elles.

La list de Python permet més coses que l'ArrayList de Java:

  • Una llista de Python pot inicialitzar-se amb una sèrie d'elements:
Python
1
2
3
assignatures = ["prg", "bd", "lm", "edd", "si", "ang", "fol"]
# O bé:
assignatures = list(("prg", "bd", "lm", "edd", "si", "ang", "fol"))
  • Els elements d'una mateixa llista de Python poden ser de distints tipus:
Python
dadesInsti = ["Jaume II el Just", "Camí la Dula", 46760, True]

Exemples d'inicialització de les distintes col·leccions de Python

Python
1
2
3
4
amics = ["Pep", "Pepa", "Pepet", "Pep"]     # Llista
siOno = ("s", "S", "n", "N")                # Tupla (1)
animals = {"gos", "gat", "peix", "tortuga"} # Conjunt
notes = {"Pep":9, "Pepa":10, "Pepet":7}     # Diccionari (2)
  1. Una tupla és una llista però invariable (no podrem afegir, modificar ni llevar elements).
  2. Cada tipus de col·lecció té el seu delimitador.

O bé, així:

Python
1
2
3
4
amics = list(("Pep", "Pepa", "Pepet", "Pep"))       # Llista
siOno = tuple(("s", "S", "n", "N"))                 # Tupla
animals = set(("gos", "gat", "peix", "tortuga"))    # Conjunt
notes = dict((Pep=9, Pepa=10, Pepet=7))             # Diccionari

Vegem amb exemples algunes operacions que podem fer amb les llistes de Python:

Operacions amb llistes
Python
# AFEGIR
amics = ["Pep", "Pepa"]     # Creem una llista d'amics
amics.append("Pepet")       # Afegim elements al final: ['Pep', 'Pepa', 'Pepet']
amics.insert(1, "Pepeta")    # Afegim en la 2a pos: ['Pep', 'Pepeta', 'Pepa', 'Pepet']

# CONSULTAR
print(amics[0])             # Consultem el 1r element ('Pep')
amiguet = amics[2]          # Consultem el 3r element ('Pepa')

print(len(amics))           # Consultem la grandària de la llista: 4

print("Pepa" in amics)      # Consultem si Pepa està en amics: True
print(amics.index("Pepa"))  # Consultem l'índex de Pepa: 2
#print(amics.index("Josep")) # Consultem índex d'element inexistent: error!!!

print(amics)                # Mostrem la llista de colp: ['Pep', 'Pepeta', 'Pepa', 'Pepet']
print(*amics)               # Mostrem els distints elements: Pep Pepeta Pepa Pepet
print("Amics:", *amics, sep='\n - ')    # Mostrarà cada element en una linia:

'''
Amics:
- Pep
- Pepeta
- Pepa
- Pepet
'''

# RECORRER
for i in range (len(amics)):    # Recorrem la llista amb un for tradicional
    print(amics[i])

for amic in amics:              # Recorrem la llista amb un bucle foreach
    print(amic)

# MODIFICAR
amics[1] = "Pau"    # Modifiquem el 2n element: ['Pep', 'Pau', 'Pepa', 'Pepet']

# ORDENAR
amics.sort()        # Ordenenm la llista

# ESBORRAR
amics.pop(1)            # Esborrem el 2n element: ['Pep', 'Pepa', 'Pepeta']
amics.remove("Pepeta")  # Esborrem l'element Pepeta: ['Pep', 'Pepa']
amics.clear()           # Buidem la llista: []
Exercici 12. Llistes en Java

Fes un programa en Java sobre una agenda d'amics. Haurà de mostrar el següent menú, demanar una opció i executar-la. Tornarà a fer-se el mateix fins eixir del programa:

  • Introduir un amic. Es demanarà el nom de l'amic, si ja existia l'amic en la llista avisarà i no el tornarà a posar.
  • Esborrar un amic. Es demanarà el nom i l'esborrarà. Avisarà que s'ha esborrat o que no estava.
  • Mostrar la llista. Cada amic en una línia. Al final dirà quants amics hi ha.
  • Mostrar per inicial. Es demanarà una lletra i es mostraran tots els amics que comencen per eixa lletra.
  • Modificar amic. Es demanarà una posició i un nou nom i el modificarà. Avisarà del resultat.
  • Ordenar la llista alfabèticament.
  • Buidar la llista.
  • Eixir.
Exercici 12b. LListes en Python

Fes el Python el programa anterior sobre l'agenda d'amics.

Diccionaris de Java: la classe HashMap

Un HashMap és un diccionari en Java. Un diccionari està format per parelles clau-valor, on no té importància l'ordre de les parelles.

Veiem-ho amb un exemple, on volem guardar el preu de cada article:

Exemple HashMap
HashMap.java
import java.util.HashMap;

public class ExempleHashMap {
    public static void main(String[] args) {
        HashMap<String, Double> articles = new HashMap();

        articles.put("tomaques", 4.5);
        articles.put("cebes", 2.2);
        articles.put("melons", 1.5);
        articles.put("melons", 1.7);    // Sobreescriu l'entrada de melons

        System.out.println("Tinc " + articles.size() + " articles:");
        System.out.println(articles); // {melons = 1.7, tomaques = 4.5, cebes = 2.2}
        System.out.println("Què vols comprar? ");
        String art = funcionsIO.readTextC("");

        if (!articles.containsKey(art)) {
            System.out.println("No existeix l'article");
        }
        else {
            System.out.println("Són a " + articles.get(art) + " €/kg");
        }

        System.out.println("ARTICLES\tPREU");
        for (String a : articles.keySet()) {    // Recorrem el diccionari
            System.out.println(a + "\t" + articles.get(a));
        }
    }
}

Però els HashMap tenen més mètodes: per a esborrar una entrada, esborrar tot el diccionari, comprovar si està buit, comprovar si existeix tal valor...

Pots investigar més creant un programa al teu IDE: posael nom d'un HashMap i el punt, i apareixeran tots els mètodes amb informació de com emprar-los. O bé:

HashMap en Java

Diccionaris de Python: la classe dict

Un dict és un diccionari en Python. Per tant, com en Java, també està format per parelles clau-valor, on no té importància l'ordre de les parelles.

Veiem-ho amb un exemple, on volem guardar el preu de cada article:

Exemple Diccionari en Python
Python
articles = {"peres":4.5, "cebes":2.2}   # Creem diccionari amb 2 entrades
#articles = dict(peres=4.5, cebes=2.2)  # Altra forma de crear el diccionari

articles["melons"] = 1.5    # Afig una entrada de melons
articles["melons"] = 1.7    # Modifica l'entrada de melons

print(f"Tinc {len(articles)} articles") # Grandària del diccionari

print(articles)

art = input("Què vols comprar? ")

if not art in articles:     # Comprovem si existeix la clau
    print("No existeix l'article")
else:                       # Accedim al valor corresponent d'eixa clau
    print(f"Són a {articles[art]} €/kg")    # O bé: articles.get(art)

print("ARTICLE", "PREU", sep="\t")
for art in articles.keys():     # Recorrem el diccionari. O bé in articles
    print(art, articles[art], sep="\t")

Pots practicar o ampliar sobre els diccionaris de Python en:

Diccionaris en Python