4 Tipos de datos compuestos
4.1 Colecciones de datos
Colecciones de datos con distinta estructura y semántica.
- Arrays
- Vectores
- Matrices
- Tuplas
- Diccionarios
- Conjuntos
4.2 Arrays
Un array es una colección ordenada de datos de un mismo tipo.
El tipo del array se infiere automáticamente a partir de los tipos de sus elementos. Si los elementos son de distintos tipos se convierten al tipo más específico de la jerarquía de tipos del que los tipos de los elementos son subtipos.
Se construyen escribiendo sus elementos separados por comas, puntos y comas o espacios entre corchetes.
> [1, 2, 3]
julia3-element Vector{Int64}:
1
2
3
> [1.0, "julia", true]
julia3-element Vector{Any}:
1.0
"julia"
true
4.3 Arrays multidimensionales
Los arrays pueden estructurar sus elementos en múltiples dimensiones. Dependiendo el número de dimensiones tenemos distintos tipos de arrays:
4.3.1 Funciones de arrays
length(A)
: Devuelve el número de elementos del arrayA
.eltype(A)
: Devuelve el tipo de los elementos del arrayA
.ndims(A)
: Devuelve el número de dimensiones del arrayA
.size(A)
: Devuelve una tupla con los tamaños de las dimensiones del arrayA
.size(A, n)
: Devuelve el tamaño de la dimensiónn
del arrayA
.axes(A)
: Devuelve una tupla con los índices válidos de cada dimensión del arrayA
.axes(A, n)
: Devuelve un rango con los índices válidos de la dimensiónn
del arrayA
.eachindex(A)
: Devuelve un iterador sobre los índices de los elementos del arrayA
.
4.3.2 Constructores de arrays
zeros(dim)
: Devuelve un array de la dimensiones indicadas por la tupladim
con todos sus elementos ceros.ones(dim)
: Devuelve un array de la dimensiones indicadas por la tupladim
con todos sus elementos unos.fill(a, dim)
: Devuelve un array de la dimensiones indicadas por la tupladim
con todos sus elementos igualesa
.rand(dim)
: Devuelve un array de la dimensiones indicadas por la tupladim
con todos sus elementos números aleatorios entre 0 y 1.trues(dim)
: Devuelve un array de la dimensiones indicadas por la tupladim
con todos sus elementostrue
.falses(dim)
: Devuelve un array de la dimensiones indicadas por la tupladim
con todos sus elementosfalse
.
4.3.3 Ejemplos de constructores de arrays
> zeros(3) # Vector de tamaño 3
julia3-element Vector{Float64}:
0.0
0.0
0.0
> rand(3,2) # Matriz de tamaño 3 x 2
julia3×2 Matrix{Float64}:
0.1469 0.891839
0.953462 0.395681
0.819468 0.720606
> fill(π, 2, 2)
julia2×2 Matrix{Irrational{:π}}:
π π
π π
4.3.4 Redimensionamiento de arrays
La siguientes funciones permiten cambiar las dimensiones de un array, reestructurando sus elementos:
reshape(A, dim)
: Devuelve el array que resulta de redimiensionar el arrayA
con las dimensiones indicadas por la tupladim
.permutedims(A)
: Devuelve el array de resulta de trasponer el arrayA
.
El array resultante debe tener los mismos elementos que el array original, por lo que si las dimensiones no son compatibles se produce un error.
4.3.5 Ejemplo de redimensionamiento de arrays
> v = [1, 2, 3, 4, 5, 6]
julia6-element Vector{Int64}:
1
2
3
4
5
6
> reshape(v, 2, 3)
julia2×3 Matrix{Int64}:
1 3 5
2 4 6
> reshape(v, 3, 2)
julia3×2 Matrix{Int64}:
1 4
2 5
3 6
> permutedims(reshape(v, 3, 2))
julia2×3 Matrix{Int64}:
1 2 3
4 5 6
4.3.6 Comprensión de arrays
Una potente técnica de creación de arrays es la comprensión de arrays, que consiste en generar los elementos del array a partir de uno o varios iteradores.
[exp for i = ite]
: Devuelve el vector cuyos elementos resultan de evaluar a expresiónexp
para cada valori
del iteradorite
.[exp for i = ite if cond]
: Devuelve el vector cuyos elementos resultan de evaluar a expresiónexp
para cada valori
del iteradorite
que cumpla la condicióncond
.
Se pueden utilizar varios iteradores para crear arrays de varias dimensiones.
> [i^2 for i = 1:4]
julia4-element Vector{Int64}:
1
4
9
16
> [i^2 for i = 1:4 if i % 2 == 0]
julia2-element Vector{Int64}:
4
16
> [i+j for i = 1:2, j = 3:4]
julia2×2 Matrix{Int64}:
4 5
5 6
4.4 Vectores
Los vectores son arrays de una dimensión.
Se construyen escribiendo sus elementos separados por comas o puntos y comas entre corchetes.
> v = [1, 2, 3]
julia3-element Vector{Int64}:
1
2
3
> length(v)
julia3
> eltype(v)
juliaInt64
> ndims(v)
julia1
> size(v)
julia3,)
(
> eachindex(v)
juliaBase.OneTo(3)
4.4.1 Acceso a los elementos de un vector
El acceso a los elementos de un vector es mediante índices. Cada elemento del vector tiene asociado un índice entero que se corresponde con su posición desde 1 hasta el número de elementos.
v[i]
: Devuelve el elemento del vectorv
con índicei
.
Si se proporciona un índice no válido se produce un error.
Las palabras reservadas begin
y end
se utilizan para referirse al primer y último índice de un vector.
4.4.2 Ejemplo de acceso a los elementos de un vector
> v = [2, 4, 6]
julia3-element Vector{Int64}:
2
4
6
> v[2]
julia4
> v[end]
julia6
> v[4]
julia: BoundsError: attempt to access 3-element Vector{Int64} at index [4]
ERROR:
Stacktrace1] getindex(A::Vector{Int64}, i1::Int64)
[Base ./array.jl:861
@ 2] top-level scope
[REPL[4]:1 @
4.4.3 Acceso a múltiples elementos de un vector
Es posible extraer varios elementos de un vector a la vez indicando los índices mediante un rango o un vector de enteros.
v[i:j]
: Devuelve un vector con los elementos del vectorv
desde el índicei
alj
.v[u]
: Devuelve un vector con los elementos del vectorv
correspondientes a los índices del vectoru
.
> v = [2, 4, 6, 8];
julia
> v[2:3]
julia2-element Vector{Int64}:
4
6
> v[[2,4,3]]
julia3-element Vector{Int64}:
4
8
6
4.4.4 Modificación de los elementos de un vector
También es posible modificar un vector asignando nuevos elementos mediante los índices.
v[i] = a
: Añade el elementoa
al vectorv
en el índicei
.
> v = [2, 4, 6]
julia3-element Vector{Int64}:
2
4
6
> v[2] = 0
julia0
> v
julia3-element Vector{Int64}:
2
0
6
4.4.5 Añadir elementos a un vector
Las siguientes funciones permiten añadir elementos al final de un vector:
push!(v, a)
: Añade el elementoa
al final del vectorv
.append!(v, u)
: Añade los elementos del vectoru
al final del vectorv
.
> v = [];
julia
> push!(v, 1)
julia1-element Vector{Any}:
1
> append!(v, [2, 3])
julia3-element Vector{Any}:
1
2
3
> v
julia3-element Vector{Any}:
1
2
3
4.4.6 Recorrer un vector
Una operación habitual es recorrer los elementos de un vector para hacer cualquier operación con ellos. Existen dos posibilidades: recorrer el vector por índice o por valor.
> v = [2, 4, 6];
julia
> for i in v # Recorrido por valor
juliaprintln(i)
end
2
4
6
> for i in eachindex(v) # Recorrido por índice
juliaprintln(v[i])
end
2
4
6
4.4.7 Operaciones con vectores numéricos
minimum(v)
: Devuelve el menor elemento del vectorv
.maximum(v)
: Devuelve el mayor elemento del vectorv
.argmin(v)
: Devuelve el índice del menor elemento del vectorv
.argmax(v)
: Devuelve el índice del mayor elemento del vectorv
.sum(v)
: Devuelve la suma de los elementos del vectorv
.prod(v)
: Devuelve el producto de los elementos del vectorv
.unique(v)
: Devuelve un vector con los elementos dev
sin repetir.
> v = [4, 2, 3];
julia
> maximum(v)
julia4
> argmax(v)
julia1
> sum(v)
julia9
> prod(v)
julia24
4.4.8 Ordenación de vectores
sort(v, rev=true)
: Devuelve el vector que resulta de ordenar en orden ascendente los elementos del vectorv
. Si se pasatrue
al parámetrorev
el orden es descendente.sort!(v, rev=true)
: Ordena el vectorv
en orden ascendente. Si se pasatrue
al parámetrorev
el orden es descendente.reverse(v)
: Devuelve el vector con los elementos del vectorv
en orden inverso.reverse!(v)
: Modifica el vectorv
poniendo sus elementos en orden inverso.
4.4.9 Ejemplo de ordenación de vectores
> v = [4, 2, 3];
julia
> sort(v)
julia3-element Vector{Int64}:
2
3
4
> reverse(v)
julia3-element Vector{Int64}:
3
2
4
> v
julia3-element Vector{Int64}:
4
2
3
> reverse!(v)
julia3-element Vector{Int64}:
3
2
4
> v
julia3-element Vector{Int64}:
3
2
4
4.4.10 Extensión de funciones a vectores
Si una función recibe un parámetro del tipo de los elementos de un vector, se puede aplicar la función a cada uno de los elementos del vector, extendiendo la llamada de la función sobre los elementos del vector. Para ello basta con añadir un punto entre el nombre de la función y el paréntesis de los argumentos.
f.(v)
: Devuelve el vector que resulta de aplicar la funciónf
a cada uno de los elementos del vectorv
.
En la llamada a la función hay que pasarle com argumentos tantos vectores como parámetros tenga la función. Si los vectores son de distinto tamaño, se reciclan los de menor tamaño.
Si la función no devuelve ningún valor el resultado es un vector de valores nothing
.
La extensión de funciones también funciona con operadores, poniendo el punto delante del operador.
4.4.11 Ejemplo de extensión de funciones a vectores
> v = [1, 4, 9];
julia
> sqrt.(v)
julia3-element Vector{Float64}:
1.0
2.0
3.0
> v .^ 2
julia3-element Vector{Int64}:
1
16
81
> base = [2, ℯ, 10];
julia
> log.(base, v)
julia3-element Vector{Float64}:
0.0
1.3862943611198906
0.9542425094393249
4.4.12 Filtrado de vectores
Otra operación bastante común son los filtros de vectores. Se puede filtrar un vector a partir de un vector de booleanos del mismo tamaño.
v[u]
: Devuelve el vector con los elementos que tienen el mismo índice que los valorestrue
del vector booleanou
.
Esto permite aplicar filtros a partir de condiciones que devuelvan un vector de booleanos.
4.4.13 Ejemplo de filtrado de vectores
> v = [1, 2, 3, 4];
julia
> v[[true, false, true, false]]
julia2-element Vector{Int64}:
1
3
> v .% 2 .== 0 # Condición
julia4-element BitVector:
0
1
0
1
> v[v .% 2 .== 0] # Filtro de números pares
julia2-element Vector{Int64}:
2
4
4.4.14 Álgebra lineal con vectores
u
+v
: Devuelve el vector que resulta de la suma de los vetoresu
yv
.u
-v
: Devuelve el vector que resulta de la resta de los vetoresu
yv
.a * v
: De vuelve el vector que resulta de multiplicar el vectorv
por el escalara
.v'
: Devuelve el vector que resulta de trasponer el vectorv
. Siv
es un vector fila,v'
es un vector columna y viceversa.
Con el paquete LinearAlgebra
también están disponibles las siguientes funciones:
dot(u, v)
: Devuelve el producto escalar de los vectoresu
yv
.norm(v)
: Devuelve la norma (módulo) del vectorv
.
4.4.15 Ejemplo de álgebra lineal con vectores
using LinearAlgebra
> u = [1, 2, 3]; v = [1, 0, 2];
julia
> u + v
julia3-element Vector{Int64}:
2
2
5
> 2u
julia3-element Vector{Int64}:
2
4
6
> dot(u, v) # Producto escalar
julia7
> u'v # Producto escalar
julia7
> norm(v) # Norma o módulo
julia2.23606797749979
> u / norm(u) # Vector unitario
julia3-element Vector{Float64}:
0.2672612419124244
0.5345224838248488
0.8017837257372732
4.5 Matrices
Las matrices son arrays de dos dimensiones (filas x columnas).
Se construyen escribiendo sus elementos entre corchetes, separando los elementos por espacio y las filas por punto y coma ;
.
> A = [1 2 3; 4 5 6]
julia2×3 Matrix{Int64}:
1 2 3
4 5 6
> length(A)
julia6
> eltype(A)
juliaInt64
> ndims(A)
julia2
> size(A)
julia2, 3) (
4.5.1 Acceso a los elementos de una matriz
El acceso a los elementos de una matriz es mediante índices. Cada elemento de la matriz tiene asociado un par de índices enteros que se corresponde la fila y la columna que ocupa.
A[i, j]
: Devuelve el elemento de la matrizA
con índice de filai
e índice de columnaj
.
Si se proporciona algún índice no válido se produce un error.
También se puede acceder a los elementos de una matriz mediante un único índice. En ese caso se obtiene el elemento con ese índice en el vector que resulta de concatenar los elementos de la matriz por columnas.
4.5.2 Ejemplo de acceso a los elementos de una matriz
> A = reshape(1:6, 2, 3)
julia2×3 reshape(::UnitRange{Int64}, 2, 3) with eltype Int64:
1 3 5
2 4 6
> A[2, 1]
julia2
> A[4]
julia4
4.5.3 Acceso a múltiples elementos de una matriz
Es posible extraer varios elementos de una matriz a la vez indicando los índices de las filas y las columnas mediante un rango o un vector de enteros.
A[i:j, k:l]
: Devuelve una matriz con los elementos desde el índice de filai
alj
y el índice de columnak
all
de la matrizA
.A[u, w]
: Devuelve una matriz con los elementos correspondientes a los índices de fila del vectoru
y los índices de columna del vectorw
de la matrizA
.
4.5.4 Ejemplo de acceso a múltiples elementos de una matriz
> A = reshape(1:9, 3, :)
julia3×3 reshape(::UnitRange{Int64}, 3, 3) with eltype Int64:
1 4 7
2 5 8
3 6 9
> A[1:2, 2:3]
julia2×2 Matrix{Int64}:
4 7
5 8
> A[[1, 3], [3, 1]]
julia2×2 Matrix{Int64}:
7 1
9 3
> A[2, :] # Segundo vector fila
julia3-element Vector{Int64}:
2
5
8
4.5.5 Modificación de los elementos de una matriz
También es posible modificar una matriz asignando nuevos elementos mediante los índices de fila y columna.
A[i, j] = a
: Añade el elementoa
a la matrizA
con el índice de filai
y el índice de columnaj
.
> A = zeros(2, 3)
julia2×3 Matrix{Float64}:
0.0 0.0 0.0
0.0 0.0 0.0
> A[2,3] = 1
julia1
> A
julia2×3 Matrix{Float64}:
0.0 0.0 0.0
0.0 0.0 1.0
4.5.6 Concatenación de matrices
Dos o más matrices pueden concatenarse horizontal o verticalmente siempre que sus dimensiones sean compatibles.
[A B]
: Devuelve la matriz que resulta de concatenar horizontalmente las matricesA
yB
. Ambas matrices deben tener el mismo número de filas.[A; B]
: Devuelve la matriz que resulta de concatenar verticalmente las matricesA
yB
. Ambas matrices deben tener el mismo número de columnas.
4.5.7 Ejemplo de concatenación de matrices
> A = zeros(2, 2)
julia2×2 Matrix{Float64}:
0.0 0.0
0.0 0.0
> B = ones(2, 1)
julia2×1 Matrix{Float64}:
1.0
1.0
> C = ones(1, 3)
julia1×3 Matrix{Float64}:
1.0 1.0 1.0
> D = [A B]
julia2×3 Matrix{Float64}:
0.0 0.0 1.0
0.0 0.0 1.0
> [D ; C]
julia3×3 Matrix{Float64}:
0.0 0.0 1.0
0.0 0.0 1.0
1.0 1.0 1.0
4.5.8 Concatenación de vectores
También es posible concatenar varios vectores horizontalmente o verticalmente para formar una matriz.
hcat(v...)
: Devuelve la matriz que resulta de concatenar horizontalmente los vectores del vectorv
.vcat(v...)
: Devuelve la matriz que resulta de concatenar verticalmente los vectores del vectorv
.
4.5.9 Ejemplo de concatenación de vectores
> v = [[1, 2, 3], [4, 5, 6]]
julia2-element Vector{Vector{Int64}}:
1, 2, 3]
[4, 5, 6]
[
> hcat(v...)
julia3×2 Matrix{Int64}:
1 4
2 5
3 6
> v = [[1 2 3], [4 5 6]]
julia2-element Vector{Matrix{Int64}}:
1 2 3]
[4 5 6]
[
> vcat(v...)
julia2×3 Matrix{Int64}:
1 2 3
4 5 6
4.5.10 Recorrido de matrices
Una operación habitual es recorrer los elementos de una matriz para hacer una operación con ellos. El recorrido se suele hacer con dos bucles iterativos anidados.
> A = [1 2 3; 4 5 6]
julia2×3 Matrix{Int64}:
1 2 3
4 5 6
> for i = 1:size(A, 1), j = 1:size(A, 2) # Recorrido por filas
juliaprintln(A[i, j])
end
1
2
3
4
5
6
> for j = 1:size(A, 2), i = 1:size(A, 1) # Recorrido por columnas
juliaprintln(A[i, j])
end
1
4
2
5
3
6
4.5.11 Operaciones con matrices numéricas
minimum(A)
: Devuelve el menor elemento de la matrizA
.maximum(A)
: Devuelve el mayor elemento de la matrizA
.argmin(A)
: Devuelve los índices de fila y columna del menor elemento de la matrizA
.argmax(A)
: Devuelve los índices de fila y columna del mayor elemento de la matrizA
.sum(A)
: Devuelve la suma de los elementos de la matrizA
.prod(A)
: Devuelve el producto de los elementos de la matrizA
.
> A = [1 2 3; 4 5 6]
julia2×3 Matrix{Int64}:
1 2 3
4 5 6
> minimum(A)
julia1
> argmax(A)
juliaCartesianIndex(2, 3)
> sum(A)
julia21
> prod(A)
julia720
4.5.12 Extensión de funciones a matrices
Al igual que para vectores, se puede aplicar una una función a todos los elementos de una matriz. Para ello basta con añadir un punto entre el nombre de la función y el paréntesis de los argumentos.
f.(A)
: Devuelve la matriz que resulta de aplicar la funciónf
a cada uno de los elementos de la matrizA
.
En la llamada a la función hay que pasarle como argumentos tantos vectores como parámetros tenga la función. Si las matrices son de distinto tamaño, se reciclan las de menor tamaño.
La extensión de funciones también funciona con operadores, poniendo el punto delante del operador.
4.5.13 Ejemplo de extensión de funciones a matrices
> A = [1 2 3; 4 5 6]
julia2×3 Matrix{Int64}:
1 2 3
4 5 6
> sqrt.(A)
julia2×3 Matrix{Float64}:
1.0 1.41421 1.73205
2.0 2.23607 2.44949
> A .+ 1
julia2×3 Matrix{Int64}:
2 3 4
5 6 7
4.5.14 Álgebra lineal con matrices
A
+B
: Devuelve la matriz que resulta de la suma de las matricesA
yB
. Ambas matrices deben tener las mismas dimensiones.A
-B
: Devuelve la matriz que resulta de la resta de las matricesA
yB
. Ambas matrices deben tener las mismas dimensiones.a * A
: Devuelve la matriz que resulta de multiplicar la matrizA
por el escalara
.A * B
: Devuelve la matriz producto de las matricesA
yB
. El número de columnas deA
debe coincidir con el número de filas deB
.A'
: Devuelve la matriz traspuesta de la matrizA
.transpose(A)
: Devuelve la matriz traspuesta de la matrizA
.
4.5.15 Ejemplo de álgebra lineal con matrices
> A = [1 2 3; 4 5 6]
julia2×3 Matrix{Int64}:
1 2 3
4 5 6
> B = [1 1 1; 2 2 2]
julia2×3 Matrix{Int64}:
1 1 1
2 2 2
> A + B
julia2×3 Matrix{Int64}:
2 3 4
6 7 8
> C = A'
julia3×2 adjoint(::Matrix{Int64}) with eltype Int64:
1 4
2 5
3 6
> A * C
julia2×2 Matrix{Int64}:
14 32
32 77
> C * A
julia3×3 Matrix{Int64}:
17 22 27
22 29 36
27 36 45
4.5.16 Álgebra lineal con matrices
El paquete LinearAlgebra
define las siguientes funciones:
Matrix(I, n, n)
. Devuelve la matriz identidad de dimensiónn
.diag(A)
: Devuelve un vector con los elementos de la diagonal principal de la matrizA
.norm(A)
: Devuelve la norma de Frobenius de la matrizA
.tr(A)
: Devuelve la traza de la matriz cuadradaA
.det(A)
: Devuelve el determinante de la matriz cuadradaA
.inv(A)
: Devuelve la matriz inversa de la matriz cuadradaA
.A \ B
: Devuelve el vectorx
solución del sistema de ecuaciones \(Ax = B\), dondeA
es una matriz cuadrada yB
es un vector del mismo tamaño que el número de filas o columnas deA
.
4.5.17 Ejemplo de álgebra lineal con matrices
using LinearAlgebra
> Matrix(I, 3, 3)
julia3×3 Matrix{Bool}:
1 0 0
0 1 0
0 0 1
> A = [1 2 3; 0 1 0; 1 0 1]
julia3×3 Matrix{Int64}:
1 2 3
0 1 0
1 0 1
> diag(A)
julia3-element Vector{Int64}:
1
1
1
> norm(A)
julia4.123105625617661
> tr(A)
julia3
> det(A)
julia-2.0
> inv(A)
julia3×3 Matrix{Float64}:
-0.5 1.0 1.5
0.0 1.0 0.0
0.5 -1.0 -0.5
> B = [10, 2, 4]
julia3-element Vector{Int64}:
10
2
4
> A \ B # Solución del sistema Ax = B
julia3-element Vector{Float64}:
3.0
2.0
1.0
4.5.18 Álgebra lineal con matrices
Otras funciones más avanzadas del paquete LinearAlgebra
son:
eigvals(A)
: Devuelve un vector con los autovalores de la matrizA
.eigvecs(A)
: Devuelve la matriz con los autovectores de la matrizA
.factorize(A)
: Devuelve las matrices resultantes de la factorización de la matrizA
. La factorización dependerá de las propiedades deA
(ver tipos de factorización)
4.5.19 Ejemplos de Álgebra lineal con matrices
using LinearAlgebra
> A = [1 2; 3 1]
julia2×2 Matrix{Int64}:
1 2
3 1
> eigvals(A)
julia2-element Vector{Float64}:
-1.4494897427831779
3.4494897427831783
> eigvecs(A)
julia2×2 Matrix{Float64}:
-0.632456 0.632456
0.774597 0.774597
> B = [1 2; 2 1]
julia2×2 Matrix{Int64}:
1 2
2 1
> factorize(B)
juliaFloat64, Tridiagonal{Float64, Vector{Float64}}}
LU{:
L factor2×2 Matrix{Float64}:
1.0 0.0
0.5 1.0
:
U factor2×2 Matrix{Float64}:
2.0 1.0
0.0 1.5
4.5.20 Copia de tipos de datos compuestas
En Julia cuando se asigna una variable de un tipo de datos compuesto a otra variable, no se hace una copia de la estructura de datos referenciada por la primera variable, sino que se la nueva variable apunta a la misma dirección de memoria de la estructura de datos (copia por referencia). El resultado son dos variables que apuntan a la misma estructura de datos y cualquier cambio en una de ellas se verá reflejado en la otra.
Para hacer copias por valor de un tipo de datos compuesto debe usarse explícitamente la siguiente función:
b = copy(a)
: Crea una copia de la estructura de datos referencia pora
y asigna su referencia ab
.
4.5.21 Ejemplo de copia de tipos de datos compuestos
> v = [1, 2, 3];
julia
> u = copy(v); # Copia por valor
julia
> u[2] = 0;
julia
> u
julia3-element Vector{Int64}:
1
0
3
> v
julia3-element Vector{Int64}:
1
2
3
> u = v; # Copia por referencia
julia
> u[2]=0;
julia
> v
julia3-element Vector{Int64}:
1
0
3
4.6 Tuplas
Una tupla es una colección ordenada de tamaño fijo que puede contener elementos de distintos tipos.
Generalmente se usan para pasar parámetros o devolver valores de funciones.
Se crean escribiendo sus elementos separados por comas entre paréntesis.
Las tuplas son inmutables, es decir, una vez creadas no pueden cambiarse sus elementos.
> () # Tupla vacía
julia
()
> (1, "enero", 2020)
julia1, "enero", 2020)
(
> t = (1, "enero", 2020)
julia1, "enero", 2020)
(
> typeof(t)
juliaTuple{Int64, String, Int64}
4.6.1 Tuplas con nombres
Es posible asignar un nombre a cada uno de los elementos de la tupla. Para ello cada elemento de la tupla con nombre debe escribirse con la sintaxis nombre = valor
.
> t = (día = 1, mes = "enero", año = 2020)
julia= 1, mes = "enero", año = 2020)
(día
> typeof(t)
juliaNamedTuple{(:día, :mes, :año), Tuple{Int64, String, Int64}}
No puede haber dos elementos con el mismo nombre en una tupla.
La ventaja de usar tuplas con nombres es que podemos acceder a sus elementos por nombre, además de por índice.
4.6.2 Acceso a los elementos de una tupla
Como las tuplas tienen orden, podemos acceder a sus elementos mediante índices, al igual que con los arrays de una dimensión.
t[i]
: Devuelve el elemento con íncidei
de la tuplat
.
Si la tupla tiene nombres también es posible acceder a sus elementos mediante los nombres.
t.x
: Devuelve el elemento con nombrex
de la tuplat
.
> t = (día = 1, mes = "enero", año = 2020)
julia= 1, mes = "enero", año = 2020)
(día
> t[2]
julia"enero"
> t.año
julia2020
> julia
4.6.3 Asignación múltiple de tuplas
Es posible asignar los elementos de una tupla a distintas variables en una sola asignación.
x, y, ... = t
: Asigna a las variables x
, y
, etc los elementos de la tupla t
en orden. Si el número de variables es menor que el tamaño de la tupla, los últimos elementos quedan sin asignar.
x, y... = t
: Asigna el primer elemento de la tupla t
a la variable x
y la tupla con los elementos restantes a la variable y
.
4.6.4 Ejemplo de asignación múltipe de tuplas
> t = (1, "enero", 2020)
julia1, "enero", 2020)
(
> d, m, a = t
julia1, "enero", 2020)
(
> d
julia1
> m
julia"enero"
> a
julia2020
> d, ma... = t
julia1, "enero", 2020)
(
> d
julia1
> ma
julia"enero", 2020) (
4.7 Diccionarios
Un diccionario es una colección asociativa sin orden cuyos elementos son pares formados por una clave y un valor asociado a la clave.
Se parecen a las tuplas con nombre, pero, a diferencia de estas, son mutables, es decir, su contenido se puede alterar.
Se construyen con la siguiente constructor:
Dict(k1 => v1, ...)
: Crea un diccionario con los pares indicados en formatoclave => valor
.
En un diccionario no pueden existir dos pares con la misma clave, de modo que si se repite una clave se sobrescribe el par anterior.
4.7.1 Ejemplo de diccionarios
> Dict() # Diccionario vacío
juliaDict{Any, Any}()
> d = Dict("ES" => "Euro", "US" => "Dollar", "CN" => "Yuan")
juliaDict{String, String} with 3 entries:
"CN" => "Yuan"
"ES" => "Euro"
"US" => "Dollar"
> typeof(d)
juliaDict{String, String}
4.7.2 Comprensión de diccionarios
Al igual que para arrays se puede usar la técnica de compresión para generar diccionarios a partir de uno o varios iteradores.
Dict(kexp => vexp for i = ite)
: Devuelve el diccionario cuyos pares están formados por la claves y valores resultan de evaluar las expresioneskexp
yvexp
respectivamente, para cada valori
del iteradorite
.Dict(kexp => vexp for i = ite if cond)
: Devuelve el diccionario cuyos pares están formados por la claves y valores resultan de evaluar las expresioneskexp
yvexp
respectivamente, para cada valori
del iteradorite
que cumpla condicióncond
.
Se pueden utilizar más de un iterador después de la palabra reservada for
.
4.7.3 Ejemplo de comprensión de diccionarios
> Dict(i => i^2 for i = 1:4)
juliaDict{Int64, Int64} with 4 entries:
4 => 16
2 => 4
3 => 9
1 => 1
> Dict(i => i^2 for i = 1:4 if i % 2 == 0)
juliaDict{Int64, Int64} with 2 entries:
4 => 16
2 => 4
> Dict((i, j) => i + j for i = 1:2, j = 3:4)
juliaDict{Tuple{Int64, Int64}, Int64} with 4 entries:
2, 4) => 6
(1, 3) => 4
(1, 4) => 5
(2, 3) => 5 (
4.7.4 Acceso a los elementos de un diccionario
Para acceder a los valores de un diccionario se utilizan sus claves asociadas entre corchetes.
d[k]
: Devuelve el valor asociado a la clavek
en el diccionariod
.
Si la clave no existe en el diccionario se produce un error.
Para evitar errores es conveniente usar alguna de las siguientes funciones:
haskey(d, k)
: Devuelvetrue
la clavek
está en diccionariod
yfalse
en caso contrario.get(d, k, v)
: Devuelve el valor asociado a la clavek
en el diccionariod
o el valorv
si la clavek
no existe.get!(d, k, v)
: Devuelve el valor asociado a la clavek
en el diccionariod
. Si la clavek
no existe en el diccionariod
añade el par con la clavek
y el valorv
y devuelve el valorv
.
4.7.5 Ejemplo de acceso a los elementos de un diccionario
> d = Dict("ES" => "Euro", "US" => "Dollar", "CN" => "Yuan")
juliaDict{String, String} with 3 entries:
"CN" => "Yuan"
"ES" => "Euro"
"US" => "Dollar"
> d["ES"]
julia"Euro"
> d["JP"]
julia: KeyError: key "JP" not found
ERROR:
Stacktrace1] getindex(h::Dict{String, String}, key::String)
[Base ./dict.jl:481
@ 2] top-level scope
[REPL[22]:1
@
> get(d, "JP", "Dollar")
julia"Dollar"
> get!(d, "JP", "Yen")
julia"Yen"
> d
juliaDict{String, String} with 4 entries:
"CN" => "Yuan"
"ES" => "Euro"
"JP" => "Yen"
"US" => "Dollar"
4.7.6 Recorrido de las claves y valores de un diccionario
Las siguientes funciones permiten obtener todas las claves, valores y pares de un diccionario.
keys(d)
: Devuelve un iterador con las claves del diccionariod
.values(d)
: Devuelve un iterador con los valores del diccionariod
.
Estos iteradores permiten recorrer fácilmente los pares de un diccionario.
4.7.7 Ejemplo de recorrido de las claves y valores de un diccionario
> d = Dict("ES" => "Euro", "US" => "Dollar", "CN" => "Yuan")
juliaDict{String, String} with 3 entries:
"CN" => "Yuan"
"ES" => "Euro"
"US" => "Dollar"
> keys(d)
juliafor a Dict{String, String} with 3 entries. Keys:
KeySet "CN"
"ES"
"US"
> values(d)
juliafor a Dict{String, String} with 3 entries. Values:
ValueIterator "Yuan"
"Euro"
"Dollar"
> for k = keys(d)
juliaprintln("$k = $(d[k])")
end
= Yuan
CN = Euro
ES = Dollar
US
> for (k, v) = d
juliaprintln("$k = $v")
end
= Yuan
CN = Euro
ES = Dollar US
4.7.8 Añadir elementos a un diccionario
Se pueden añadir pares nuevos a un diccionario de la siguiente manera:
d[k] = v
: Añade el par con clavek
y valorv
al diccionariod
. Si la clavek
ya existía en el diccionariod
, cambia su valor asociado porv
.push!(d, k => v)
: Añade el par con clavek
y valor asociadov
al diccionariod
.
> d = Dict("ES" => "Euro", "US" => "Dollar")
juliaDict{String, String} with 2 entries:
"ES" => "Euro"
"US" => "Dollar"
> d["CN"] = "Yuan"
julia"Yuan"
> push!(d, "JP" => "Yen")
juliaDict{String, String} with 4 entries:
"CN" => "Yuan"
"ES" => "Euro"
"JP" => "Yen"
"US" => "Dollar"
4.7.9 Eliminar elementos de un diccionario
Para eliminar un par de un diccionario se utiliza la siguiente función:
delete!(d, k)
: Elimina el par cuya clave esk
del diccionariod
.
> d = Dict("ES" => "Euro", "US" => "Dollar", "CN" => "Yuan")
juliaDict{String, String} with 3 entries:
"CN" => "Yuan"
"ES" => "Euro"
"US" => "Dollar"
> delete!(d, "US")
juliaDict{String, String} with 2 entries:
"CN" => "Yuan"
"ES" => "Euro"
4.8 Conjuntos
Un conjunto es una colección de elementos del mismo tipo sin orden y sin repeticiones.
Se construyen con la siguiente constructor:
Set(a)
: Crea un conjunto con los elementos del arraya
.
Al igual que para arrays el tipo se infiere automáticamente a partir de los tipos de sus elementos. Si los elementos son de distintos tipos se convierten al tipo más específico de la jerarquía de tipos del que los tipos de los elementos son subtipos.
Un conjunto no puede tener elementos repetidos, por lo que si el array contiene elementos repetidos solo se incluyen una vez.
4.8.1 Ejemplo de construcción de conjuntos
> Set()
juliaSet{Any}()
> c = Set([1, "2", 3])
juliaSet{Any} with 3 elements:
"2"
3
1
> typeof(c)
juliaSet{Any}
4.8.2 Añadir elementos a un conjunto
Para añadir elementos a un conjunto se utiliza la siguiente función:
push!(c, e)
: Añade el elementoe
al conjuntoc
.
Si el elemento que se quiere añadir es de distinto tipo que los elemento del conjunto y no puede convertirse a este tipo, se produce un error.
4.8.3 Ejemplo de añadir elementos a un conjunto
> c = Set(1:3)
juliaSet{Int64} with 3 elements:
2
3
1
> push!(c, 4)
juliaSet{Int64} with 4 elements:
4
2
3
1
> push!(c, "cinco")
julia: MethodError: Cannot `convert` an object of type String to an object of type Int64
ERROR:
Closest candidates areconvert(::Type{T}, ::T) where T<:Number at /usr/share/julia/base/number.jl:6
convert(::Type{T}, ::Number) where T<:Number at /usr/share/julia/base/number.jl:7
convert(::Type{T}, ::Base.TwicePrecision) where T<:Number at /usr/share/julia/base/twiceprecision.jl:262
...
4.8.4 Eliminar elementos de un conjunto
Para eliminar elementos de un conjunto se utiliza la siguiente función:
delete!(c, e)
: Elimina el elementoe
del conjuntoc
.
> c = Set(1:3)
juliaSet{Int64} with 3 elements:
2
3
1
> delete!(c, 2)
juliaSet{Int64} with 2 elements:
3
1
4.8.5 Recorrido de los elementos de un conjunto
Un conjunto puede utilizarse también como un iterador para recorrer sus elementos.
> c = Set(1:3)
juliaSet{Int64} with 3 elements:
2
3
1
> for i = c
juliaprintln(i)
end
2
3
1
4.8.6 Pertenencia e inclusión de conjuntos
in(e, c)
,e ∈ c
: Devuelvetrue
si el elementoe
pertenece al conjuntoc
yfalse
en caso contrario.e ∉ c
: Devuelvetrue
si el elementoe
no pertenece al conjuntoc
yfalse
en caso contrario.issubset(a, b)
,a ⊆ b
: Devuelvetrue
si todos los elementos dea
pertenecen ab
yfalse
en caso contrario.a ⊈ b
: Devuelvetrue
si hay algún elemento dea
que no pertenece ab
.a ⊊ b
: Devuelvetrue
si el conjuntoa
está contenido estrictamente en el conjuntob
, es decir, todos los elementos dea
pertenecen ab
peroa
yb
son distintos.isdisjoint(a, b)
: Devuelvetrue
si los conjuntosa
yb
no tienen elementos en común yfalse
en caso contrario.
4.8.7 Ejemplos de pertenencia e inclusión de conjuntos
> a = Set(1:3);
julia
> in(2, a)
juliatrue
> 3 ∉ a
juliafalse
> b = Set([3, 2, 1]);
julia
> a ⊊ b
juliafalse
> a ⊆ b
juliatrue
> isdisjoint(a, b)
juliafalse
4.8.8 Álgebra de conjuntos
union(a, b)
,a ∪ b
: Devuelve el conjunto unión de los conjuntosa
yb
.intersect(a, b)
,a ∩ b
: Devuelve el conjunto intersección de los conjuntosa
yb
.setdiff(a, b)
: Devuelve el conjunto diferencia del conjuntoa
yb
.symdiff(a, b)
: Devuelve el conjunto diferencia simétrica de los conjuntosa
yb
.
Existen versiones de estas funciones acabadas en !
que sobreescriben el conjunto dado como primer argumento con el resultado de la operación.
4.8.9 Ejemplo de álgebra de conjuntos
> a = Set(1:3)
juliaSet{Int64} with 3 elements:
2
3
1
> b = Set(2:2:6)
juliaSet{Int64} with 3 elements:
4
6
2
> union(a, b)
juliaSet{Int64} with 5 elements:
4
6
2
3
1
> intersect(a, b)
juliaSet{Int64} with 1 element:
2
> setdiff(a, b)
juliaSet{Int64} with 2 elements:
3
1
> symdiff(a, b) == setdiff(a ∪ b, a ∩ b)
juliatrue