Estructuras de Datos

Estructuras de Datos

Las estructurtas de datos son formatos especiales de datos que permiten guardar, organizar y manipular información. En particular, cada estructura especifica la forma en la cual se pueden realizar operaciones sobre los datos que contiene y a la vez sobre qué tipo de datos trabajan.

Las estructuras de datos ocultan al programador la manera en que se maneja la memoria y la gestionan de forma eficiente, por ende genera eficiencia en los algoritmos que los implementan.

Existen numerosas estructuras de datos cada una diseñada para una aplicación en específico, Julia incorpora algunos tipos de datos básicos y sus procedimientos correspondientes, sin embargo no incorpora por defecto todos los tipos conocidos. Por ello, la comunidad de Julia ha trabajado en un paquete que incorpora diferentes estructuras de datos procurando rendimiento (revisar el paquete DataStructures.jl).

A continuación, se disertará sobre algunos de los tipos de datos básicos incorporados por defecto en Julia.

Rangos

(:)(start,[step],stop)

Esta estructura permite crear secuencias de números, desde un número dado (start ) hasta otro (stop) con un tamaño de paso ([step]) que puede ser inidicado de forma opcional.

begin
	range₁ = -5:10
	range₂ = 0:2:10
	range₃ = 0:10.0
end
0.0:1.0:10.0

Por defecto el tamaño del paso es 1. Si es requerido Julia realiza una conversión automática de tipos de datos. En general el rango puede ser tipo UnitRange o StepRange.

typeof(range₁)
UnitRange{Int64}
typeof(range₂)
StepRange{Int64,Int64}
typeof(range₃)
StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}

Puede notar que el tipo de dato de cada elemento del range está determinado infiriendo este (de forma automática) por cualquiera de los tipos de datos de: start, step o stop.

Para crear un rango también puede utilizarse el constructor OneTo (perteneciente al módulo Base), que garantiza el valor inicial de la secuencia es 1 al igual que el paso.

range₄ = Base.OneTo(10)
Base.OneTo(10)
range₄[5]
5

Array

Los arrays son un tipo de estructura que contiene datos relacionados, con ellos pueden ser representados vectores y matrices.

En Julia los Arrays son listas, que pueden contener más de un tipo de dato, según este sea creado o inicializado, además implementa métodos para incrementar y eliminar elementos. También, a diferencia de otras estructuras los array pueden tener datos duplicados.

Inicialización de arrays

El array puede ser inicializado de diversas maneras, como se contempla a continuación:

Usando el constructor explícito

array₁ = Array{Float64}(undef,5,2,2)
5×2×2 Array{Float64,3}:
[:, :, 1] =
 6.94883e-310  6.94883e-310
 6.94883e-310  6.94883e-310
 6.94883e-310  6.94883e-310
 6.94883e-310  6.94883e-310
 6.94881e-310  6.94883e-310

[:, :, 2] =
 6.94881e-310  6.94883e-310
 6.94881e-310  6.94883e-310
 6.94883e-310  6.94883e-310
 6.94882e-310  6.94883e-310
 6.94883e-310  6.94881e-310
array₁[5][1]
6.9488105687428e-310

En el constructor explícito debe especificarse:

  • El tipo de dato (en el ejemplo Float64).

  • Las dimensiones del array (en el ejemplo al array se especifica 3 dimensiones).

  • El tamaño del array, el keyword undef debe ser declarado, posteriormente se indica la cantidad cantidad de elementos por dimensión.

NOTA: Aunque se desea tener un array vacío, al especificar el tamaño de array, Julia rellena los elementos con datos contenidos en el garbage.

El array vacío (sin especificar el tamaño) se puede inicializar de las siguientes maneras:

array₂ = Array{Any,1}()
Any[]
array₃ = []
Any[]

En las inicializaciones anteriores el array acepta cualquier tipo de valor, pues su definición contempla elementos con el supertipo Any (en el caso de array₂ se define de forma explícita y en el de array₃ de forma implícita).

Pueden existir casos en que el array solo deba contener elementos de un número limitado de tipos, en tales casos la declaración del tipo del array puede ser decalarado mediante Union, por ejemplo: Array{Union{Int64,Float64,String},2}. En el ejemplo el array solo podrá contener elementos del tipo: Int64, Float64 o String.

array₄ = Array{Float64,1}()
Float64[]
array₅ = Float64[]
Float64[]

Los arrays anteriores están vacios, pero solo aceptan elementos que son del tipo Float64 o que pueden ser promovidos a ese tipo (por ejemplo Int64 puede ser convertido a Float64).

push!(array₄,2)
1-element Array{Float64,1}:
 2.0
##push!(array₅,"Hola")

NOTAS: Con el método push! se pueden agregar elementos al array.

Si ya se conoce el contenido del array, este puede ser inicializado como “array literal”, es decir puede ser creado de forma manual.

array₆ = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

El array anterior, que es de 1 dimensión, es conocido como array columna, en lugar de utilizar , puede utilizar ;. Un array fila puede ser creado si cada elemento del array es separado mediante un espacio.

array₇ = [1 2 3]
1×3 Array{Int64,2}:
 1  2  3

Como puede notar el tipo de dato entre array₆ y array₇ difieren, el primero es de una dimensión mientras que el segundo es de dos dimensiones. Lo anterior significa que en array₇ cada elemento se encuentra en columnas diferentes de la matriz.

Lo anterior puede suponer varias ventajas, ya que se pueden realizar operaciones conocidas entre matrices.

array₇*array₆
1-element Array{Int64,1}:
 14
array₆*array₇
3×3 Array{Int64,2}:
 1  2  3
 2  4  6
 3  6  9

En el caso de un array de dos dimensiones, existen diferentes formas en que este puede ser inicializado de formas manual.

array₈ = [[1,2,3] [4,5,6] [7,8,9]]
3×3 Array{Int64,2}:
 1  4  7
 2  5  8
 3  6  9

En el caso anterior el array fue creado por columnas, mediante el ingreso de arrays columnas separados por un espacio. Similares resultados se obtienen al utilizar el método hcat.

hcat([1,2,3],[4,5,6])
3×2 Array{Int64,2}:
 1  4
 2  5
 3  6
array₉ = [[1 2 3]; [4 5 6]]
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

En el caso anterior el array fue creado mediante filas, mediante el ingreso de arrays filas separados por una ;. Similares resultados se obtienen al utilizar el método vcat.

vcat([1 2 3], [4 5 6] )
2×3 Array{Int64,2}:
 1  2  3
 4  5  6

Inicialización de arrays especiales

Julia implementa métodos que pueden ser útiles para crear array de forma rápida

Array de ceros

Un array de ceros puede ser creado con el método zeros, que admite como argumentos el tipo de datos y luego las dimensiones del array.

zeros(Int64,4)
4-element Array{Int64,1}:
 0
 0
 0
 0
zeros(Float64,4,4)
4×4 Array{Float64,2}:
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
Array de unos

Un array de unos puede ser creado con el método ones, que admite como argumentos el tipo de datos y luego las dimensiones del array.

ones(Float64,3)
3-element Array{Float64,1}:
 1.0
 1.0
 1.0
ones(Float64,3,3)
3×3 Array{Float64,2}:
 1.0  1.0  1.0
 1.0  1.0  1.0
 1.0  1.0  1.0

NOTA: Puede leer más sobre inicialización de arrays y métodos para el manejo de arrays en:

Accediendo a los elementos de un Array

Se accede a los elementos de un array con [] e indicando la posición de elemento.

array₆
3-element Array{Int64,1}:
 1
 2
 3
array₆[1]
1

Como puede ser observado, a diferencia de otros lenguajes de programación, Julia tiene indexación base-1, lo que significa que para el primer elemento del array tiene índice 1 no 0.

array3dim = cat([1 2; 3 4],["Hola 1" "Hola 2"; "Hola 3" "Hola 4"],[5 6; 7 8],dims=3)
2×2×3 Array{Any,3}:
[:, :, 1] =
 1  2
 3  4

[:, :, 2] =
 "Hola 1"  "Hola 2"
 "Hola 3"  "Hola 4"

[:, :, 3] =
 5  6
 7  8
array3dim[1,1,2]
"Hola 1"

En el ejemplo anterior se accede a un elemento de un array de 3 dimensiones, indicando la posición con una terna de números. Sin embargo, se puede acceder a más de un elemento extrayendo un subarray del primero.

array₆[2:3]
2-element Array{Int64,1}:
 2
 3

Los índices de los elementos que se desean extraer pueden ser indicados mediante un objeto tipo range como se muestra en el ejemplo.

array3dim[:,:,2]
2×2 Array{Any,2}:
 "Hola 1"  "Hola 2"
 "Hola 3"  "Hola 4"

Con el símbolo : se indica que todos los elementos de una dimensión del array deben ser extraidos; en el caso del array de una dimensión, todos los elementos del mismo.

array3dim[1,1:2,3]
2-element Array{Any,1}:
 5
 6
array3dim[1:2,2,1]
2-element Array{Any,1}:
 2
 4

En los ejemplos anteriores, se recorre el arreglo por columna y por fila respectivamente.

Para un mejor rendimiento, se recomienda recorrer un array por columna, debido a la forma en que Julia almacena los elementos del array en memoria, como se muestra a continuación.

array₁₀ = [1:3 4:6 7:9 ] 
3×3 Array{Int64,2}:
 1  4  7
 2  5  8
 3  6  9

Note que array₁₀ es un array de dos dimensiones y aunque se accede a los elementos indicando dos índices, también puede accederse mediante un solo índice.

[array₁₀[1],array₁₀[3],array₁₀[4],array₁₀[6],array₁₀[7],array₁₀[end]]
6-element Array{Int64,1}:
 1
 3
 4
 6
 7
 9

Ello indica que Julia almacena los elementos del array de forma concecutiva por columnas. Por ende, si el array se recorre por filas se tendrán que hacer cálculos adicionales llevando un costo de tiempo; por esa razón el costo por acceder a un array por columnas es menor que si se hiciera por filas.

Métodos útiles

Julia implementa numerosos métodos para trabajar con los arrays. A continuación, se mencionan algunas de las más básicas que permiten realizar varias tareas.

En Julia los argumentos de las funciones se pasan por referencia, es decir, se pasa a la función no solo el valor contenido en la variable sino que, también se pasa la referencia a la variable original. Lo anterior significa que, cualquier cambio realizado al argumento dentro de la función, dicho cambio se verá reflejado en la variable original.

Por ello, en Julia se sigue una convención cuando se diseña funciones y esta es: si la función modifica el argumento se denota añadiendo al nombre el símbolo !. La convención mencionada es algo que se mira en varias funciones, existiendo dos versiones de las mismas (las que modifican la variable original y las que no).

array₁₁ = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3

El método push! modifica el array, agregando un elementos al final del mismo y devuelve el array modificado.

push!(array₁₁,4)
4-element Array{Int64,1}:
 1
 2
 3
 4
push!(array₁₁,5,6,7)
7-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7
array₁₁
7-element Array{Int64,1}:
 1
 2
 3
 4
 5
 6
 7

El método pushfirst! añade un elementos al inicio del array.

pushfirst!(array₁₁,-1,0)
9-element Array{Int64,1}:
 -1
  0
  1
  2
  3
  4
  5
  6
  7

El método pop! elimina y retorna el último elemento del array.

pop!(array₁₁)
7
array₁₁
8-element Array{Int64,1}:
 -1
  0
  1
  2
  3
  4
  5
  6

El método popfirst! elimina y retorna el primer elemento del array.

popfirst!(array₁₁)
-1
array₁₁
7-element Array{Int64,1}:
 0
 1
 2
 3
 4
 5
 6

El método deleteat! elimina un elemento indicado la posición de este dentro del array y devuelve el array modificado.

deleteat!(array₁₁,6)
6-element Array{Int64,1}:
 0
 1
 2
 3
 4
 6
deleteat!(array₁₁,3:5)
3-element Array{Int64,1}:
 0
 1
 6

El método splice! tiene diferentes formas de uso; entre ellas reemplazar elementos del array, indicando la posición del elemento por reemplazar y devuelve el valor del elemento reemplazado.

splice!(array₁₁,3,3)
6
array₁₁
3-element Array{Int64,1}:
 0
 1
 3

Otra forma de uso es la de eliminar elementos, para ello solo se pasa como argumento el array a modificar y la posición del elemento, el método devuelve el valor del elemento eliminado.

splice!(array₁₁,2)
1
array₁₁
2-element Array{Int64,1}:
 0
 3

Otro caso de uso para splice! es la eliminar un elemento y agregar elementos indicándolos por medio de una lista.

splice!(array₁₁,2,[3,4,5,6])
3
array₁₁
5-element Array{Int64,1}:
 0
 3
 4
 5
 6
splice!(array₁₁,2,[1,2,3])
3
array₁₁
7-element Array{Int64,1}:
 0
 1
 2
 3
 4
 5
 6

También pueden insertarse elementos elementos entre otros, como se ilustra.

splice!(array₁₁,4:3,0)
Int64[]
array₁₁
8-element Array{Int64,1}:
 0
 1
 2
 0
 3
 4
 5
 6

Para que splice! funcione de la manera mostrada anteriormente, es necesario que el índice de los elementos donde se desea insertaer se indiquen de la forma n:n-1.

Existe un método para vaciar un array, este método presenta los dos casos: el que modifca el array y el que no, el método empty y empty!.

empty(array₁₁)
Int64[]
array₁₁
8-element Array{Int64,1}:
 0
 1
 2
 0
 3
 4
 5
 6
empty!(array₁₁)
Int64[]
array₁₁
Int64[]

El método maximum devuelve el máximo valor entre los valores del elemento de un array.

maximum([1 2; 3 4])
4

El método minimum devuelve el mínimo valor entre los valores del elemento de un array.

minimum([1 2; 3 4])
1

Merece la atención los métodos anteriores, pues devuelven el menor o mayor valor (según sea el caso) al llamado de una función, para más información puede leer del manual de Julia las secciones relacionadas con dichas funciones.

El método isempty comprueba si el array está vacío o no.

isempty(array₁₁)
true
isempty(array₁₀)
false

La función length devuelve la cantidad de elementos que contiene el array.

length(array₁₁)
0
length(array₁₀)
9

La funión size devuelve las una tupla con las dimensiones del array.

size(array₄)
(1,)
size(array₁)
(5, 2, 2)

NOTA: Más funciones e información acerca de los arrays en Julia puede encontrarlo en el manual en la seción Multi-dimensional Arrays

Precauciones

Al trabajar con arrays en alguna ocasión se querrá hacer una copia de esta.

array₁₂ = [1,2,3]
3-element Array{Int64,1}:
 1
 2
 3
arraycopy₁ = array₁₂
3-element Array{Int64,1}:
 1
 2
 3

El problema de las líneas anteriores es: tanto array₁₂ como arraycopy₁ apuntan a la misma dirección de memoria, es decir, la línea de código arraycopy₁ = array₁₂ no asigna el valor de array₁₂ en arraycopy₁.

Para comprobar lo anterior puede usarse el operador de igualdad estricto.

arraycopy₁ === array₁₂
true

Además cualquier modificación realizado con arraycopy₁ se verá reflejado en array₁₂.

push!(arraycopy₁,5)
4-element Array{Int64,1}:
 1
 2
 3
 5
array₁₂
4-element Array{Int64,1}:
 1
 2
 3
 5

Para hacer una copia de una array puede utilizarse el método copy, el cual realiza una copia del array indicado en su argumento.

arraycopy₂ =  copy(array₁₂)
4-element Array{Int64,1}:
 1
 2
 3
 5
arraycopy₂ === array₁₂
false
push!(arraycopy₂,5)
5-element Array{Int64,1}:
 1
 2
 3
 5
 5
array₁₂
4-element Array{Int64,1}:
 1
 2
 3
 5

Tuplas

Las tuplas (Tuples) son listas, pero a diferencia de los arrays son inmutables. Lo anterior quiere decir que una vez creada la tupla esta no puede ser: modificada, eliminada o sobreescrita, como sí sucede con los arrays. Al igual que los arrays, las tuplas pueden contener diferentes tipos de datos.

Para crear una tupla, los elementos de esta se encierran entre (). Se accede a los elementos de las tuplas de la misma forma en que se acceden a los elementos de un array.

tuple₁ = (1,2,3,"Hello, World!")
(1, 2, 3, "Hello, World!")
typeof(tuple₁)
Tuple{Int64,Int64,Int64,String}

Para comprobar la inmutabilidad de las tuplas, se puede intentar modificar el tercer elemento de tuple₁ y de array₁₂ (en el caso de tuple₁ se obtendrá un error).

##tuple₁[3] = 33
array₁₂[3] = 33; array₁₂
4-element Array{Int64,1}:
  1
  2
 33
  5

Cuando se quiere crear una tupla de un solo elemento, al final del elemento debe colocarse ,; ya que el uso de ( ) serían interpretados como elementos de agrupación. Para mantener coherencia, se permite lo mismo si se inicializa una tupla con más de un elemento.

tuple₂ = (11,) ##Compare con la asignación (11), en el cual tuple₂ sería una variable con valor 11 del tipo Int64
(11,)
tuple₃ = (11,12,13,) 
(11, 12, 13)

A menudo las tuplas son implementadas en el retorno de funciones, por ejemplo, la función divrem que retorna el cociente y el resto de la división euclidiana. Cuando sucede lo anterior los valores de la tupla se puede descomprimir en variables.

cociente,resto = divrem(39,5)
(7, 4)
[cociente, resto]
2-element Array{Int64,1}:
 7
 4

Una discusión sobre el tipo de tuplas puede encontrarse en Tipos de Tuplas.

De forma opcional, los componentes de las tuplas pueden ser nombrados, en dicho caso se construye una tupla con nombre.

tuple₄ = (a = 2, b = 4)
(a = 2, b = 4)

Para acceder a los elementos de una tupla nombrada se puede usar la sintaxis tuple.nombre, además de la indexación normal tuple[i].

[tuple₄.a, tuple₄[:b], tuple₄[1],tuple₄[2]]
4-element Array{Int64,1}:
 2
 4
 2
 4

Diccionarios

Los diccionarios son estructuras de datos que guardan datos en forma de clave-valor, es decir es una colección asociativa de datos que no tienen un orden establecido.

Creando diccionarios

Los diccionarios son creados con el constructor Dict, este puede contener como argumentos las claves asociadas a los valores o puede usarse sin argumentos (en dicho caso es vacío).

dict₁ = Dict("Nombre"=>"Juan", "Edad"=>25, 3.0=>50)
Dict{Any,Any} with 3 entries:
  "Nombre" => "Juan"
  "Edad"   => 25
  3.0      => 50

Como puede observarse, los diccionarios pueden aceptar como clave cualquier valor y tipo de dato. Para asociar los valores a las claves se utiliza el operador =>, que corresponde a la función Pair().

dict₂ = Dict()
Dict{Any,Any}()

dict₂ es un diccionario vacío, pero al igual que los array es una estructura de datos mutable, por lo que pueden añadirse elementos como se haría con array asociativos en otros lenguajes de programación.

begin
	dict₂[1] = "Hola" ##La clave es un valor del tipo Int64
	dict₂["dos"] = "Mundo" ##La clave es un valor del tipo String
	dict₂[:x] = "Tercer elemento" ##La clave es un valor del tipo Symbol
	dict₂
end
Dict{Any,Any} with 3 entries:
  :x    => "Tercer elemento"
  "dos" => "Mundo"
  1     => "Hola"

En un diccionario las claves deben ser únicas, no pueden existir dos claves con el mismo nombre.

[dict₂[1], dict₂["dos"], dict₂[:x]]
3-element Array{String,1}:
 "Hola"
 "Mundo"
 "Tercer elemento"

Accediendo a los elementos de un array

El acceso a los elementos del diccionario se realiza de forma similar a los arrays, mediante [ ].

Dict("nombre"=>"Pedro", "nombre"=>"Rodríguez") ##El diccionario solo tiene una única clave 'nombre'
Dict{String,String} with 1 entry:
  "nombre" => "Rodríguez"

Métodos usados con diccionarios

Para conocer si una determinada clave existe se puede utilizar el método haskey, este retorna true o false dependiendo si existe o no.

[haskey(dict₂,5), haskey(dict₂,"dos"), haskey(dict₂,1)]
3-element Array{Bool,1}:
 0
 1
 1

De igual manera se puede determinar si un par clave => valor existe con el método in.

[in(1=>"Hola",dict₂), in(1=>"Mundo",dict₂)]
2-element Array{Bool,1}:
 1
 0

Las claves de un diccionario pueden obtenerse uando el método keys, el cual retorna un iterador. Se puede utilizar el método collect para transformarlo en un array.

keys(dict₂)
Base.KeySet for a Dict{Any,Any} with 3 entries. Keys:
  :x
  "dos"
  1
collect(keys(dict₂))
3-element Array{Any,1}:
  :x
  "dos"
 1

Los valores de un diccionario pueden obtenerse uando el método values, el cual retorna una lista con ellas.

values(dict₂)
Base.ValueIterator for a Dict{Any,Any} with 3 entries. Values:
  "Tercer elemento"
  "Mundo"
  "Hola"
collect(values(dict₂))
3-element Array{Any,1}:
 "Tercer elemento"
 "Mundo"
 "Hola"

Tipos de datos y los diccionarios

En los diccionarios mostrados, el tipo de dato para la clave y los valores podian ser de diferentes tipos. La definición del diccionario es la siguiente:

typeof(dict₂)
Dict{Any,Any}

Como se observa Dict{Any,Any} indica que el tipo de dato para la clave es Any y para el valor es Any.

Puede crearse un dicconario que restrinja el tipo de datos para la clave y valor, de esta manera puede crearse una estructura más compleja.

typeof(Dict{String,Int64}("1"=>1, "2"=>2))
Dict{String,Int64}
typeof(Dict{Int64,String}(1=>"1", 2=>"2"))
Dict{Int64,String}
typeof(Dict{Symbol,Int64}(:x=>1, :y=>2))
Dict{Symbol,Int64}

Los diccionarios y las tuplas nombradas pueden ser vistas como similares, sin embargo, existe una diferencia fundamental: que las tuplas son inmutables mientras que los diccionarios son mutables.

Conjuntos

Los conjuntos son una colección desordenada de datos, pero tiene la peculiaridad de no contener elementos duplicados. Así como los arrays y los diccionarios son tipos de datos mutables.

Al igual que los arrays y los diccionarios, los conjuntos pueden contener cualquier tipo de dato. Al momento de crear el conjunto el tipo de dato puede ser especificado, como en otras estructuras de datos; si el tipo de dato no es especificado, Julia analiza los elementos y define el tipo de datos del conjunto.

Creación de conjuntos

Los conjuntos son creados con el constructor set, cuyos elementos son especificados mediante un array.

set₁ = Set()
Set{Any}()

set₁ es un conjunto vacío que acepta cualquier valor.

set₂ = Set{Float64}()
Set{Float64}()

set₂ es un conjunto vacío que acepta valores del tipo Float64.

set₃ = Set([1,2,3,3])
Set{Int64} with 3 elements:
  2
  3
  1

Como puede notar, en el caso de set₃ Julia analiza que los elementos del conjunto set₃ deben ser del tipo Int64. Dado que los conjuntos no pueden tener elementos duplicados, finalmente set₃ solo tiene un elemento con valor 3.

Con el método push! se puede agregar datos a los conjuntos, pero dado que es una colección de elementos desordenados no puede usarse el método pushfirts!. De la misma manera con el método pop! se puede eliminar un elemento del conjunto indicándolo.

push!(set₃,5)
Set{Int64} with 4 elements:
  2
  3
  5
  1
pop!(set₃,5)
5
set₃
Set{Int64} with 3 elements:
  2
  3
  1

Métodos relacionados con los conjuntos

Julia implementa diferentes métodos para trabajar con los conjuntos (muchos de ellos también puede usarse con los diccionarios).

set₄ = Set(["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado"])
Set{String} with 7 elements:
  "Lunes"
  "Martes"
  "Viernes"
  "Domingo"
  "Sábado"
  "Miércoles"
  "Jueves"
set₅ = Set([1,2,3,"Sábado","Domingo"])
Set{Any} with 5 elements:
  "Sábado"
  2
  3
  "Domingo"
  1

Con el método union los conjuntos pueden fusionarse, retornando el conjunto resultante. Es decir, un conjunto cuyo elementos se ecuentra en cualquiera de los conjuntos.

union(set₅,set₄)
Set{Any} with 10 elements:
  "Lunes"
  "Martes"
  "Viernes"
  "Sábado"
  2
  3
  "Domingo"
  "Miércoles"
  "Jueves"
  1
union!(set₅,set₄)
Set{Any} with 10 elements:
  "Lunes"
  "Martes"
  "Viernes"
  "Sábado"
  2
  3
  "Domingo"
  "Miércoles"
  "Jueves"
  1
set₅
Set{Any} with 10 elements:
  "Lunes"
  "Martes"
  "Viernes"
  "Sábado"
  2
  3
  "Domingo"
  "Miércoles"
  "Jueves"
  1

Con el método intersect se obtiene la interseción de los conjuntos, es decir, devuelve un conjunto cuyos elementos se encuentra en ambos conjuntos.

intersect(set₄,set₅)
Set{String} with 7 elements:
  "Lunes"
  "Martes"
  "Viernes"
  "Sábado"
  "Domingo"
  "Miércoles"
  "Jueves"
intersect!(set₄,set₅)
Set{String} with 7 elements:
  "Lunes"
  "Martes"
  "Viernes"
  "Domingo"
  "Sábado"
  "Miércoles"
  "Jueves"
set₄
Set{String} with 7 elements:
  "Lunes"
  "Martes"
  "Viernes"
  "Domingo"
  "Sábado"
  "Miércoles"
  "Jueves"

Con el método setdiff se obtiene la diferencia entre dos conjuntos, es decir, un conjunto cuyos elementos se encuentran en uno de ellos no en el otro.

setdiff(set₅,set₄)
Set{Any} with 3 elements:
  2
  3
  1
setdiff!(set₅,set₄)
Set{Any} with 3 elements:
  2
  3
  1

List Comprehensions

Es un forma poderosa de crear listas o array, que también ha sido implementado en otros lenguages de programación. Tiene la peculiaridad de definir los elementos del array de manera similar a la notación constructiva en matemática. Tiene la siguiente sintaxis:

[ expresión for elemento colección]

Por ejemplo, un matemático podría decir: “Sea \(S\) el conjunto de todos los elementos \(n\), donde \(n\) es mayor o igual a \(1\) y menor o igual a \(10\). En tal caso se puede crear en Julia un conjunto que responda a la definición anterior.

set₆ = Set([n for n  1:10])
Set{Int64} with 10 elements:
  7
  4
  9
  10
  2
  3
  5
  8
  6
  1

Ahora bien, con list comprehensions se pueden utilizar condicionales que actúan como filtro, de esta manera se pueden definir conjuntos más complicados como: “Sea \(C\) el conjunto de todos los elementos \(n\); donde \(n\) es mayor o igual a \(1\), menor o igual a \(10\) y divisible entre dos”

C = [n for n  1:10 if n%2 == 0]
5-element Array{Int64,1}:
  2
  4
  6
  8
 10

Dobles iteraciones se pueden utilizar para generar arrays con list comprehensions.

tablamultiplicar₁ = [ x*y for x  1:10, y  1:10]
10×10 Array{Int64,2}:
  1   2   3   4   5   6   7   8   9   10
  2   4   6   8  10  12  14  16  18   20
  3   6   9  12  15  18  21  24  27   30
  4   8  12  16  20  24  28  32  36   40
  5  10  15  20  25  30  35  40  45   50
  6  12  18  24  30  36  42  48  54   60
  7  14  21  28  35  42  49  56  63   70
  8  16  24  32  40  48  56  64  72   80
  9  18  27  36  45  54  63  72  81   90
 10  20  30  40  50  60  70  80  90  100

En el caso anterior, se crea un array de más de dos dimensiones. Si se utiliza dos bucles de forma explícita se generan los mismos elementos, sin embargo, de esta última manera se crea un array de una dimensión.

tablamultiplicar₂ = [ x*y for x  1:10 for y  1:5]
50-element Array{Int64,1}:
  1
  2
  3
  4
  5
  2
  4
  6
  8
 10
  3
  6
  9
  ⋮
 32
 40
  9
 18
 27
 36
 45
 10
 20
 30
 40
 50

Al igual que los arrays el tipo de datos de los elementos es analizado por Julia, pero este puede ser definido de forma explícita.

typeof(Float64[n for n  1:10])
Array{Float64,1}

Tipos de estructuras como: diccionarios, tuplas y arrays, pueden ser usados para realizar iteraciones.

for i  [1,2,3]
	print(i)
end
123
tuple₄
(a = 2, b = 4)
for i  tuple₄
	print(i)
end
24
dict₂
Dict{Any,Any} with 3 entries:
  :x    => "Tercer elemento"
  "dos" => "Mundo"
  1     => "Hola"
for i  keys(dict₂)
	print(dict₂[i])
end
Tercer elementoMundoHola
for i  values(dict₂)
	print(i)
end
Tercer elementoMundoHola