Introducción a las variables en Flutter: Los Maps


Avatar de Pedro Cortez

Una clase de Flutter que puede parecer impresionante al principio es sin duda la Map. ¿Cómo crear una Map, añadirle elementos, eliminarlos, etc.? Trato de responder a estas preguntas con ejemplos simples en este artículo.


map flutter

¿Qué es un Map?

Entre las clases presentes en Flutter, una de las más difíciles de usar cuando se comienza probablemente sea el Map. Esta variable es una especie de lista en la que cada elemento se compone de dos entradas:

  • Una clave (key);
  • y un valor (value).

A diferencia de la clase List, que se representa entre corchetes [ ], el Map se coloca entre llaves { }. Por ejemplo, aquí tienes un ejemplo muy básico de un Map:

Map<dynamic, dynamic> mapNumeros = {"cero": 0, "uno": 1, "dos": 2};

Aquí, mis claves (keys) están representadas por los valores «cero», «uno» y «dos», y mis valores (values) por 0, 1 y 2.

¿Cuál es la diferencia con una lista?

La lista no contiene claves, sino índices. Por lo tanto, no puedo asignarles un valor distinto al tipo int que yo mismo defina. Mi lista comenzará inevitablemente en el índice 0, seguido por 1, 2, etc.

Crear una variable de tipo Map en Flutter

Existen varias formas de crear un widget de tipo Map, ya sea manualmente o utilizando métodos.

Crear un Map manualmente

La forma más sencilla de crear un Map en Flutter es declararlo como una variable. Para ello, basta con declararlo y especificar los tipos de claves (keys) y valores (values) que aceptará. Por ejemplo, si quiero que mi Map tenga claves del tipo Int y valores del tipo String, lo declararé así:

Map<Int, String> miMapa = {};

Las parejas de clave-valor se colocan entre llaves y se separan por comas. Por ejemplo:

Map<Int, String> miMapa = {1: "Mi primer valor", 2: "Mi segundo valor", 3: "Mi tercer valor"};

Si no sabes de antemano qué tipo de claves o valores almacenará tu Map, o si serán de tipos diferentes, puedes usar el tipo dynamic, que permite almacenar cualquier tipo de valor.

Crear un Map a partir de un solo widget List

Flutter nos permite, gracias al método .fromIterable, crear un Map a partir de un widget List que actúe como contador. Este método consta de 3 atributos:

  • El número de iteraciones, definido por la lista que utilicemos;
  • El valor key, al cual debemos asignar un valor;
  • El valor value, que también deberá definirse.

Por ejemplo, aquí tienes un ejemplo muy simple tomado de la documentación de Flutter:

final numeros = <int>[1, 2, 3];
final mapa = Map<String, int>.fromIterable(numeros,
    key: (item) => item.toString(),
    value: (item) => item * item);
print(mapa); 
↪ {1: 1, 2: 4, 3: 9}

En este caso, nuestras claves (keys) serán los valores contenidos en nuestra lista numeros. Los valores (values) serán los elementos de la lista multiplicados por sí mismos.

Por supuesto, no estás obligado a utilizar los elementos de tu lista para crear tus claves y valores. Aquí, el widget List principalmente define el número de iteraciones.

Si no asignas ningún valor a key o value, estos serán llenados automáticamente con los elementos de la lista. Por ejemplo:

final numeros = <int>[1, 2, 3];
final mapa = Map.fromIterable(numeros);
print(mapa); 
↪ {1: 1, 2: 2, 3: 3}

Crear un Map a partir de dos widgets List

Flutter nos permite, gracias al método .fromIterables, fusionar dos widgets de tipo List para crear un Map. Aquí tienes un ejemplo muy sencillo de cómo utilizarlo:

List<String> fundadores = ["Elon Musk", "Steve Jobs", "Jeff Bezos"];
List<String> empresas = ["Tesla", "Apple", "Amazon"];

Map<String, String> empresasFamosas = Map.fromIterables(fundadores, empresas);
print(empresasFamosas);
↪ {Elon Musk : Tesla, Steve Jobs : Apple, Jeff Bezos : Amazon}

Las listas que utilizas para crear tu Map deben ser del tipo especificado en la declaración de la variable. Por ejemplo, si haces un map de tipo Map<String, int>, entonces tu primera lista debe contener cadenas de caracteres y la segunda números.

Manipular los elementos de tu clase Map

Agregar un elemento a mi Map

Una o más nuevas parejas clave-valor pueden añadirse a un Map utilizando el método .addAll(). Aquí tienes un ejemplo de cómo usarlo:

Map<int, String> numeros = {0: "cero", 1: "uno", 2: "dos"};
numeros.addAll({3: "tres", 4: "cuatro"});
print(numeros);
↪ {0: "cero", 1: "uno", 2: "dos", 3: "tres", 4: "cuatro"}

Las parejas que añadas a tu Map deben ser del tipo correcto, de lo contrario recibirás un mensaje de error: The element type ‘xx’ can’t be assigned to the map key/value type ‘xx’.

¿Qué tipos de variables pueden contenerse en un Map?

Los Maps pueden contener cualquier cosa, siempre que declares correctamente tu variable. Por ejemplo, pueden contener Strings, Int, Lists, e incluso otros Maps y widgets más complejos.

Eliminar un elemento de mi Map

Los elementos de un Map no se eliminan mediante el índice, como ocurre con las listas, sino mediante las claves. Para ello, puedes utilizar el método .remove(), indicando la clave (key) del valor que deseas eliminar. Por ejemplo:

Map<String, int> numeros = {"cero": 0, "uno": 1, "dos": 2};
numeros.remove("uno");
print(numeros);
↪ {0: "cero", 2: "dos"}

¿Qué hacer si no conozco la clave que quiero eliminar, sino solo su índice?

Si quieres eliminar una pareja de tu Map pero no conoces su clave (key), puedes crear una lista con la función mapNumeros.keys.toList(). Después, puedes encontrar la clave que te interesa usando el índice y eliminarla con .remove().

El método .clear()

Otra manera de eliminar todos los elementos contenidos en tu Map es usando el método .clear(). Esto eliminará todas las claves y valores del widget. Por ejemplo:

Map<String, int> numeros = {"cero": 0, "uno": 1, "dos": 2};
numeros.clear();
print(numeros);
↪ {}

Modificar un Map

Existen dos métodos para modificar los elementos ya existentes en tu Map.

Modificar un solo elemento

Para modificar un solo elemento de tu Map, Flutter pone a tu disposición el método .update(). Este toma como parámetro la clave del valor que deseas cambiar y la nueva asignación que quieres darle. Por ejemplo:

Map<String, int> numeros = {"cero": 0, "uno": 3, "dos": 2};
numeros.update("uno", (valor) => 1);
print(numeros);
↪ {"cero": 0, "uno": 1, "dos": 2}

Además, puedes añadir un parámetro ifAbsent, en caso de que la clave que quieres modificar no exista. Por ejemplo:

Map<String, int> numeros = {"cero": 0, "uno": 1, "dos": 2};
numeros.update("tres", (valor) => 3, ifAbsent: () => 3);
print(numeros);
↪ {"cero": 0, "uno": 1, "dos": 2, "tres": 3}

Modificar todo tu Map

Para modificar todos los elementos existentes en tu Map (por ejemplo, ponerlos en mayúsculas), Flutter ofrece el método .updateAll(). Esto te permite modificar tanto las claves como los valores. Por ejemplo:

Map<String, int> numeros = {"cero": 0, "uno": 1, "dos": 2};
numeros.updateAll((clave, valor) => clave.toUpperCase());
print(numeros);
↪ {"CERO": 0, "UNO": 1, "DOS": 2}

Mostrar tu variable Map en la pantalla

Por supuesto, tus Maps no están hechas solo para almacenarse en variables, también pueden mostrarse en la pantalla. Para ello, deberás usar el widget ListView con el método .builder() y almacenar tus claves y valores en listas. Aquí te explico cómo hacerlo:

Map<dynamic, dynamic> mapNumeros = {"cero": 0, "uno": 1, "dos": 2};
List<String> listaClaves = mapNumeros.keys.toList();
List<String> listaValores = mapNumeros.values.toList();

Luego, puedes usar una de estas dos listas para construir tu ListView.builder() y utilizar los elementos contenidos en ambas para tus ListTiles. Para obtener más información sobre cómo mostrar tus listas en Flutter, te invito a consultar mi artículo sobre el widget ListView en Flutter.

Otros métodos de Flutter relacionados con Maps

Aquí tienes otras funciones que puedes usar con tus widgets de tipo Map.

containsKey()

Como su nombre indica, el método containsKey() te permite verificar si una clave aparece o no en tu Map, devolviendo un valor de tipo bool. Así es como se usa:

Map<dynamic, dynamic> mapNumeros = {"cero": 0, "uno": 1, "dos": 2};
bool contieneCero = mapNumeros.containsKey("cero");
print(contieneCero);
true

containsValue()

El método containsValue() funciona de manera similar a containsKey(), pero esta vez para los valores contenidos en el Map:

Map<dynamic, dynamic> mapNumeros = {"cero": 0, "uno": 1, "dos": 2};
bool contieneTres = mapNumeros.containsValue(3);
print(contieneTres);
false

removeWhere()

El método removeWhere() te permite eliminar las claves o valores de tu Map que cumplan una condición. Por ejemplo:

Map<dynamic, dynamic> mapNumeros = {"cero": 0, "uno": 1, "dos": 2};
mapNumeros.removeWhere((clave, valor) => clave.contains("e"));
print(mapNumeros);
↪ {"uno": 1}

forEach()

La función forEach() te permite repetir una acción tantas veces como la longitud de tu Map. Por ejemplo:

Map<dynamic, dynamic> mapNumeros = {"cero": 0, "uno": 1, "dos": 2};
mapNumeros.forEach((clave, valor) {
  print(valor);
});
0
1
2

Conclusión

Ahora ya eres capaz de crear y manipular las variables más comunes que se ven en Flutter. Sin embargo, aún te quedan dos por aprender: DateTime y URIs:

Avatar de Pedro Cortez