Swift logotipo

En este artículo, nos acercamos a las colecciones. La biblioteca estándar de Swift define tres tipos de colecciones: conjuntos, matrices y diccionarios. Comencemos visualizando de forma general que es una matriz, un diccionario y un conjunto.

  • Matriz “Fruta” = “plátano”, “pera”, “manzana”, “melocotón”. 
  • ejemploDiccionario = [0: «Manzana», 1: «Pera», 2: «Naranja]
  • var conjunto3: Set = [«Manzana», «Pera», «Naranja»]
  • var ejemploTupla = («Bart Jacobs», «pepe@example.com»)

Conceptualmente:

  1. Las matrices son conjuntos de datos ordenados del mismo tipo. 
  2. Los diccionarios son conjuntos desordenados de pares clave-valor, del mismo tipo. 
  3. Los conjuntos son conjuntos de datos NO ordenados y NO duplicados del mismo tipo y hashtables.
  4. Las tuplas son conjuntos de datos ordenados automáticamente de cualquier tipo.

Arrays o Matrices

Una matriz es un conjunto de valores ordenados e indexados a cero. Eso significa que se empieza a contar desde 0, no desde 1.

Matriz = [ posición 0, posición 1, posición 2, …, posición n]

Recordemos que un array, matriz, formación o vector, es una forma de ordenar en fila un conjunto de elementos o datos. Una matriz es una forma de ordenar datos. Por ejemplo, la matriz fruta se ordena de la siguiente manera:

Matriz “Fruta” = “plátano”, “pera”, “manzana”, “melocotón”. 

Tipo

En Swift, los valores almacenados en una matriz son siempre del mismo tipo. Esta aparente limitación permite conocer el tipo de antemano. 

Por otro lado, una matriz en Swift puede almacenar cadenas, enteros, flotantes e instancias de clase. 

Declaración de tipo

Hay varias maneras de crear una matriz en Swift y por tanto de declarar su tipo. Veamos los siguientes tres casos: 

var matriz1: Array<String>
var matriz2: [String]
var matriz3 = ["Manzana", "Pera", "Naranja"]

La primera y la segunda matriz son conceptualmente equivalentes. Lo que sucede es que la segunda línea abrevia a la primera. Array<String> o [String] indican a Swift que estamos declarando que la matriz que los elementos de la matriz serán del tipo “String”. 

La tercera matriz es lo que se conoce por literal de matriz. Es decir, sin especificar explícitamente que es un String, Int,…, double, Swift lo presupone ya que todos los elementos son del mismo tipo. 

Mutabilidad

Una matriz es mutable cuando puede cambiar. Una matriz mutable se define mediante la palabra clave “var”. Para que una matriz NO mutable, emplea la palabra clave “let”. 

Obtener y establecer valores

Para acceder a los valores almacenados en una matriz, utilizamos la sintaxis del subíndice. Es decir, [índice]. En el siguiente ejemplo, pedimos el segundo ítem de la “matriz3”. Con ello se obtiene la cadena de caracteres, «Pera».

matriz3[1]

En las matrices mutables, podemos cambiar el valor almacenado de un determinado índice de una forma muy sencilla. En el siguiente ejemplo, reemplazamos “Pera” en el índice 2 (tercera posición) por “Paco”. 

matriz3[2] = "Paco"

La unión de matrices tiene una sintaxis sencilla. En el siguiente ejemplo se suman dos matrices (“a” y “b”) inmutables para obtener una tercera matriz inmutable (“c”). La matriz resultante, “c”, no necesita ser necesariamente mutable.

let a = [10, 20, 30]
let b = [40, 50, 60]
let c = a + b

Sin embargo, si los valores almacenados en ambas matrices no son del mismo tipo, se producirá un error, como sucede en el siguiente ejemplo: 

let a = [10, 20, 30]
let b = [2.5, 3.3, 16.23]
let c = a + b

Operaciones

Una de las cosas que se puede realizar con las matrices, es invocar a un método mediante la sintaxis del punto. Si añadimos la siguiente instrucción en playground agregaremos un nuevo elemento a “matriz3”.

matriz3.append("Boniato")

También podemos ver el número de elementos que contiene “matriz3” mediante “count”. Con ello, veremos un 4 en la salida del panel de resultados. 

matriz3.count

Tambiénse puede añadir un ítem nuevo en un determinado índice llamando al método “insert(_:at:)” de la matriz como se muestra a continuación. El método “insert()” es capaz de aceptar múltiples parámetros

matriz3.insert("Cebolla", at: 2)

Métodos de conveniencia

Swift intenta ser un lenguaje conciso y sencillo. Por ejemplo, una matriz que contenga el método “isEmpty”, lo que hace es verificar si la matriz está vacía. En el fondo esto es una abreviatura de la propiedad “count”. Al final, ahorra tiempo y líneas de código. 

matriz3.isEmpty

Es decir, de otra forma necesitaríamos algo como if matriz3.count == 0 { … }. Sin embargo, con esta función directamente no hace falta el operador lógico. 

Diccionarios

Los diccionarios guardan colecciones desordenadas de valores asociados a una clave. Cada ítem de un diccionario va precedido por una palabra clave que lo identifica. 

Tipo

Las claves y los valores almacenados en un diccionario deben ser obligatoriamente del mismo tipo. 

Declaración

Crear un diccionario es algo muy parecido a crear una matriz. La única diferencia es que en la matriz se le introduce un valor y en el diccionario dos, que pueden ser de tipos distintos. Veamos el ejemplo siguiente dónde se muestran tres formas de crear un diccionario.

var diccionario1: Dictionary<String, Int>
var diccionario2: [String: Int]
var diccionario3 = ["Manzana": 13, "Pera": 18, "Naranja": 15]

El primer y el segundo diccionarios son conceptualmente equivalentes. Lo que sucede es que la segunda línea abrevia a la primera. Array<String, Int> o [String: Int] indican a Swift que estamos declarando que los elementos del diccionario serán del tipo “clave: String y valor: int”. 

El tercer diccionario es lo que se conoce por literal de diccionario. Es decir, sin especificar explícitamente que la clase/valor que son del tipo String, Int,…, double, Swift lo presupone ya que en todos los casos son del mismo tipo. 

Podemos hacer un diccionario con un tipo cualquiera desconocido:

var dict : Dictionary<String, AnyObject>

Obtener y establecer valores

La manera de obtener los datos en un diccionario es parecida a la forma de hacerlo en una matriz. La diferencia es que en a matriz se emplea el índice y en el diccionario la clave. Si observamos el siguiente ejemplo:

let valor = diccionario3["Manzana"]
print(valor)

En el Playground de Xcode veremos Optional(13) y no 13. Esto significa que Swift emplea opcionales. 

Cuando las claves son número enteros (Int) la forma de acceder a un valor de un diccionario es la misma que con las matrices. Veamos el siguiente ejemplo.

var diccionario4 = [0: "Manzana", 1: "Pera", 2: "Naranja"]
let fruta = diccionario4 [0]

Añadir, Eliminar, contar y operares varias con diccionarios

Swift permite operar con los diccionarios al igual que con las matrices. Veamos algunas operaciones. 

Si deseamos eliminar un dato a través de la clave se puede hacer como sigue: 

diccionario4.removeValue(forKey: 0)

Podemos declarar un nuevo diccionario “a trozos” como sigue: 

var diccionario = [String: Int]()
diccionario ["Naranjas"] = 2
diccionario ["Manzanas"] = 10
diccionario ["Peras"] = 5

Si deseamos vaciar un diccionario completamente: 

diccionario = [:]

Podemos añadir un elemento al diccionario: 

diccionario[3] = “fresas”

Podemos recorrer todos los valores del diccionario:

for valor in diccionario.values {
    print(value)
}

Podemos recorrer todas las claves del diccionario:

for clave in diccionario.keys {
    print(key)
}

Podemos recorrer todos los pares clave/valor:

for (clave, valor) in diccionario {
    print(key)
   print(value)
}

Conjuntos (Sets)

Los conjuntos son versiones ligeras de matrices dónde se almacenan conjuntos de elementos únicos y sin un orden establecido. 

Declaración

Trabajar con conjuntos es un poco diferente de trabajar con matrices. Veamos los siguientes ejemplos en los que declaramos tres conjuntos. La variable “conjunto1” es de tipo Set<String>, un conjunto que sólo puede contener valores de tipo “String”.

var conjunto1: Set<String>
var conjunto2 = Set<String>()
var conjunto3: Set<String> = ["Manzana", "Pera", "Naranja"]

La variable “conjunto2” es un conjunto vacío, y usamos un literal de matriz en el tercer ejemplo para crear y rellenar un conjunto mutable que contiene tres valores. Gracias a la inferencia de tipo de Swift, podemos omitir el tipo del conjunto.

var conjunto3: Set = ["Manzana", "Pera", "Naranja"]

Si nos fijamos el Set se parece mucho al array. Veamos ambas diferencias visuales. 

var conjunto3: Set = ["Manzana", "Pera", "Naranja"]
var matriz3 = ["Manzana", "Pera", "Naranja"]

El “array” no contiene el tipo “set”, el conjunto si lo tiene. Al usar “sets” aseguramos que los valores de la colección son únicos. Usamos un set siempre que el orden no sea importante y queremos asegurarnos que no se repite ningún elemento. Para guardar elementos en un set, los elementos deben ser Hashtables. 

Manipulación de conjuntos

Trabajar con conjuntos es similar a trabajar con matrices. Podemos preguntar por el número de elementos almacenados en un conjunto inspeccionando la propiedad “count” del conjunto. 

conjunto3.count

Insertar un elemento es fácil. Dado que los elementos de un conjunto no están ordenados, no es necesario especificar la ubicación del nuevo elemento.

conjunto3.insert("pistacho")

Y lo mismo se aplica a la eliminación de un elemento de un conjunto.

conjunto3.remove("Naranja")

También puede preguntar a un conjunto si contiene un elemento en particular.

conjunto3.contains("Manzana")

Hash

Los conjuntos son versiones ligeras de matrices dónde el orden de los elementos no es importante y cada uno de dichos elementos es único. Por lo que el uso de conjuntos es importante cuando el orden carece de interés. Pero, además, los conjuntos tienen la propiedad de ser hashValue.

Los datos guardados en un conjunto deben ser del tipo hash. Es decir, debe proporcionar una propiedad hashValue. Esto permite acceder a los elementos de los conjuntos, puesto que de por sí, están desordenados. 

Tuplas

Las tuplas agrupan conjuntos de datos de cualquier tipo sin que sean todos del mismo tipo. Veamos un ejemplo para explicar esto con más detalle.

import Foundation
var valorEconomico = ("EUR", 0.81)
var tiempo = (Date(), "Mensaje enviado.")
var correo = ("Pepe Trompeta", "pepe@example.com")

En la primera sentencia se declara una tupla denominada de tipo “valorEconomico(String, Int)”. La segunda tupla, tiempo, contiene una instancia de tiempo “Date()” y un String. La variable “correo” tiene ambos datos almacenados como de tipo “String”. 

Acceso a valores mediante índice

Para acceder a un valor guardado en una tupla, se puede acceder con el índice correspondiente: 

var unidad = valorEconomico.1
var mensaje = tiempo.1
var nombre = correo.0

Nombres

También se pueden bautizar a los valores almacenados en una tupla. El resultado es que puede acceder a los valores de la tupla a través de sus nombres en lugar de sus índices. 

var valorEconomico = (nombre: "EUR", valor: 0.81)

Si queremos obtener y almacenar el nombre:

let nombreUnidad = currency.nombre

Si queremos obtener y almacenar el valor:

let valor = currency.valor

Descomposición

Hay otra manera de guardar los valores en una Tupla. Para ello, veamos el siguiente ejemplo en el que descomponemos el contenido de “valorEconomico”.

let (nombreUnidad, valor) = valorEconomico

  • En el índice 0 se guarda en “nombreUnidad” dentro de “valorEconomico”. 
  • El “valor” se guarda en el índice 1. 
  • Swift infiere el tipo de ambos índices a partir de los valores guardados. El índice 0 es un “String” y el primer un “Double”. 

Si algún valor de la tupla no interesa, se puede usar un guion bajo.

let (nombreUnidad, _) = valorEconomico

El “Where” en Swift

Where en Swift es una palabra clave reservada que permite filtrar u obtener uno o varios valores. El “where” en Swift permite trabajar de forma muy intuitiva. Por ejemplo, vamos a obtener los valores primos menores de 10. 

let primos = [2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37]

  for primo in primos where primo < 10 {
      print(primo)
   }

Obtendremos el 2, el 3, el 5 y el 7. En el bucle “for”, lo que se está indicando con “where” es que por cada valor en la colección dónde la condición es: “…”. For “value” in “collection” where “condition”. Es interesante ver la cantidad de código ahorrado. Para ello, veamos como deberíamos operar si tuviéramos un “if”:

let primos = [2, 3, 5, 7, 11, 13, 17, 19, 23, 31, 37]

  for primo in primos {
    If primo < 10{
      print(primo)
    }
}

La cláusula “where” endulza la sintaxis más compleja, hace el código más conciso y fácil de leer. 

Las enumeraciones

De alguna manera, las enumeraciones simplifican el switch o estructura selectiva. Veamos el siguiente ejemplo:

enum rangoTemperatura{
 case 10, 20, 30, 1000
}

func temperaturaExtrema(temperatura: rangoTemperatura) -> String?{
  if temperatura == .1000 {
     return “alta”
  } else { return “normal”
 }
}

temperaturaExtrema(temperatura: .1000)

Primeramente, se le da un nombre al “enum” y otro para la función. La función se la llama con el mismo nombre. Para que la función emplee los “enums” debe contener entre sus paréntesis el mismo nombre que tiene la enumeración. El .1000 lo podemos escribir de esta forma simplificada o en su forma completa con rangoTemperatura.1000. Sin embargo, no es necesario escribir su forma completa porque Swift sabe a qué nos referimos. La verdad es que podemos hacer que el num sea aun más interesante:

enum rangoTemperatura{
 case 10
 case 20
 case 30 
 case 1000
 case temp(valor: Int) 
}

func temperaturaExtrema(temperatura: rangoTemperatura) -> String?{
  if temperatura >= 1000 {
     return “alta”
   } else { return “normal”
 }
}

temperaturaExtrema(temperatura: rangoTemperatura.temp(valor: 2000))

Más información

Si deseas más información sobre cómo programar en Swift consulta en la web oficial de Apple. Para cualquier otra consulta, puedes contactar con nosotros. También nos puedes ayudar descargando nuestra APP de Servicios Profesionales, freelancers y autónomos.

Leave a Comment

Your email address will not be published. Required fields are marked *

Información básica sobre protección de datos
Responsable Francisco de Asís Benavente Delgado +info...
Finalidad Gestionar y moderar tus comentarios. +info...
Legitimación Consentimiento del interesado. +info...
Destinatarios No se cederán datos a terceros, salvo obligación legal +info...
Derechos Acceder, rectificar y cancelar los datos, así como otros derechos. +info...
Información adicional Puedes consultar la información adicional y detallada sobre protección de datos en nuestra página de política de privacidad.