Colecciones iterables
Una guía interactiva para usar objetos Iterable, como listas y conjuntos.
Este tutorial te enseña cómo usar colecciones que implementan la clase Iterable —por ejemplo List y Set. Las iterables son bloques de construcción básicos para todo tipo de aplicaciones de Dart, y probablemente ya las estés usando, incluso sin darte cuenta. Este tutorial te ayuda a aprovecharlas al máximo.
Usando los editores de DartPad embebidos, puedes probar tus conocimientos ejecutando código de ejemplo y completando ejercicios.
Para aprovechar al máximo este tutorial, deberías tener conocimientos básicos de la sintaxis de Dart.
Este tutorial cubre el siguiente material:
- Cómo leer elementos de un Iterable.
- Cómo verificar si los elementos de un Iterable cumplen con una condición.
- Cómo filtrar el contenido de un Iterable.
- Cómo mapear el contenido de un Iterable a un valor diferente.
Tiempo estimado para completar este tutorial: 60 minutos.
Los ejercicios de este tutorial tienen fragmentos de código parcialmente completados.
Puedes usar DartPad para probar tus conocimientos completando el código y
haciendo clic en el botón Run.
No edites el código de prueba en la función main o debajo.
Si necesitas ayuda, expande el menú desplegable Pista o Solución después de cada ejercicio.
¿Qué son las colecciones?
#Una colección es un objeto que representa un grupo de objetos, llamados elementos. Los Iterables son un tipo de colección.
Una colección puede estar vacía o puede contener muchos elementos. Según el propósito, las colecciones pueden tener diferentes estructuras e implementaciones. Estos son algunos de los tipos de colección más comunes:
- List: Usado para leer elementos mediante sus índices.
- Set: Usado para contener elementos que pueden ocurrir solo una vez.
- Map: Usado para leer elementos usando una clave.
¿Qué es un Iterable?
#Un Iterable es una colección de elementos a los que se puede acceder secuencialmente.
En Dart, un Iterable es una clase abstracta,
lo que significa que no puedes instanciarla directamente.
Sin embargo, puedes crear un nuevo Iterable creando un nuevo List
o Set.
Tanto List como Set son Iterable,
por lo que tienen los mismos métodos y propiedades que la clase Iterable.
Un Map utiliza una estructura de datos diferente internamente,
según su implementación.
Por ejemplo, HashMap
utiliza una tabla hash
en la que los elementos (también llamados values) se obtienen mediante una clave.
Los elementos de un Map también se pueden leer como objetos Iterable
mediante la propiedad entries o values del mapa.
Este ejemplo muestra una List de int,
que también es un Iterable de int:
Iterable<int> iterable = [1, 2, 3];
La diferencia con una List es que con el Iterable,
no puedes garantizar que la lectura de elementos por índice sea eficiente.
Iterable, a diferencia de List, no tiene el operador [].
Por ejemplo, considera el siguiente código, el cual es inválido:
Iterable<int> iterable = [1, 2, 3];
int value = iterable[1];
Si lees elementos con [],
el compilador te indicará que el operador '[]'
no está definido para la clase Iterable,
lo que significa que no puedes usar [index] en este caso.
En su lugar, puedes leer elementos con elementAt(),
el cual puede recorrer los elementos del iterable hasta
llegar al elemento en esa posición.
Iterable<int> iterable = [1, 2, 3];
int value = iterable.elementAt(1);
Dependiendo de la implementación del iterable y del número de elementos,
elementAt puede tener una complejidad lineal y ser costoso.
Si planeas acceder a elementos específicos repetidamente, considera
llamar a .toList() en el iterable para convertirlo en una lista una vez,
y luego usar el operador [].
final items = veryLargeIterable().toList();
final tenthItem = items[9];
final hundredthItem = items[99];
final thousandthItem = items[999];
final lastItem = items.last;
Continúa con la siguiente sección para aprender más sobre
cómo acceder a los elementos de un Iterable.
Leer elementos
#Puedes leer los elementos de un iterable secuencialmente,
usando un bucle for-in.
Ejemplo: Usar un bucle for-in
#El siguiente ejemplo te muestra cómo leer elementos usando un bucle for-in.
Ejemplo: Usar first y last
#En algunos casos, quieres acceder solo al primer o al último elemento
de un Iterable.
Con la clase Iterable, no puedes acceder a los elementos directamente,
por lo que no puedes llamar a iterable[0] para acceder al primer elemento.
En su lugar, puedes usar first,
el cual obtiene el primer elemento.
Además, con la clase Iterable,
no puedes usar el operador [] para acceder al último elemento,
pero puedes usar la propiedad last.
En este ejemplo viste cómo usar first y last para
obtener el primer y el último elemento de un Iterable.
También es posible encontrar el primer elemento que cumpla con una condición.
La siguiente sección muestra cómo hacer eso usando un método llamado firstWhere().
Ejemplo: Usar firstWhere()
#Ya viste que puedes acceder a los elementos de un Iterable secuencialmente,
y que puedes obtener fácilmente el primer o el último elemento.
Ahora, aprenderás a usar firstWhere() para encontrar el primer elemento que
cumpla con ciertas condiciones.
Este método requiere que pases un predicate,
que es una función que devuelve true si
la entrada cumple con una determinada condición.
String element = iterable.firstWhere((element) => element.length > 5);
Por ejemplo, si quieres encontrar el primer String que tenga
más de 5 caracteres,
debes pasar un predicado que devuelva true cuando
el tamaño del elemento sea mayor que 5.
Ejecuta el siguiente ejemplo para ver cómo funciona firstWhere().
¿Crees que todas las funciones darán el mismo resultado?
En este ejemplo, puedes ver tres formas diferentes de escribir un predicado:
- Como expresión:
El código de prueba tiene una línea que utiliza la sintaxis de flecha (
=>). - Como bloque: El código de prueba tiene múltiples líneas entre llaves y una sentencia return.
- Como función:
El código de prueba está en una función externa que se pasa al
método
firstWhere()como parámetro.
No hay una forma correcta o incorrecta. Utiliza la forma que funcione mejor para ti, y que haga que tu código sea más fácil de leer y entender.
El ejemplo final llama a firstWhere() con
el parámetro con nombre opcional orElse,
el cual proporciona una alternativa cuando no se encuentra un elemento.
En este caso, se devuelve el texto 'None!' porque
ningún elemento cumple con la condición proporcionada.
Ejercicio: Practicar la escritura de un predicado de prueba
#El siguiente ejercicio es una prueba unitaria que falla y
contiene un fragmento de código parcialmente completo.
Tu tarea es completar el ejercicio escribiendo código para que las pruebas pasen.
No necesitas implementar main().
Este ejercicio introduce singleWhere().
Este método funciona de manera similar a firstWhere(),
but en este caso espera que solo un elemento del Iterable
cumpla con el predicado.
Si más de uno o ningún elemento en el Iterable
cumple con la condición del predicado,
entonces el método lanza una excepción StateError.
Tu objetivo es implementar el predicado para singleWhere() que
cumpla con las siguientes condiciones:
- El elemento contiene el carácter
'a'. - El elemento comienza con el carácter
'M'.
Todos los elementos en los datos de prueba son strings; puedes consultar la documentación de la clase para obtener ayuda.
Pista
Tu solución podría hacer uso de los métodos contains y startsWith
de la clase String.
Solución
String singleWhere(Iterable<String> items) {
return items.singleWhere(
(element) => element.startsWith('M') && element.contains('a'));
}
Comprobar condiciones
#Cuando trabajas con Iterable, a veces necesitas verificar que
todos los elementos de una colección cumplan con alguna condición.
Podrías tener la tentación de escribir una solución usando un bucle for-in como este:
for (final item in items) {
if (item.length < 5) {
return false;
}
}
return true;
Sin embargo, puedes lograr lo mismo usando el método every():
return items.every((item) => item.length >= 5);
Usar el método every() da como resultado un código que es más
legible, compacto y menos propenso a errores.
Ejemplo: Usar any() y every()
#La clase Iterable proporciona dos métodos que
puedes usar para verificar condiciones:
any(): Devuelve true si al menos un elemento cumple con la condición.every(): Devuelve true si todos los elementos cumplen con la condición.
Ejecuta este ejercicio para verlos en acción.
En el ejemplo, any() verifica que
al menos un elemento contiene el carácter a,
y every() verifica que todos los elementos
tienen una longitud igual o mayor que 5.
Después de ejecutar el código, intenta cambiar el predicado de any() para
que devuelva false:
if (items.any((item) => item.contains('Z'))) {
print('At least one item contains "Z"');
} else {
print('No item contains "Z"');
}
También puedes usar any() para verificar que ningún elemento de un Iterable
cumple con una determinada condición.
Ejercicio: Verificar que un Iterable cumple una condición
#El siguiente ejercicio ofrece práctica en el uso de los
métodos any() y every(), descritos en el ejemplo anterior.
En este caso, trabajas con un grupo de usuarios,
representados por objetos User que tienen el campo miembro age.
Usa any() y every() para implementar dos funciones:
-
Part 1: Implement
anyUserUnder18().- Devuelve
truesi al menos un usuario tiene 17 años o menos.
- Devuelve
-
Part 2: Implement
everyUserOver13().- Devuelve
truesi todos los usuarios tienen 14 años o más.
- Devuelve
Pista
Recuerda usar los métodos any y every de la clase Iterable.
Para obtener ayuda y ver ejemplos utilizando estos métodos, consulta la
discusión anterior sobre ellos.
Solución
bool anyUserUnder18(Iterable<User> users) {
return users.any((user) => user.age < 18);
}
bool everyUserOver13(Iterable<User> users) {
return users.every((user) => user.age > 13);
}
Filtrado
#Las secciones anteriores cubren métodos como firstWhere() o
singleWhere() que te pueden ayudar a encontrar un elemento que
cumpla con un determinado predicado.
¿Pero qué pasa si quieres encontrar todos los elementos que
cumplen con una determinada condición?
Puedes lograrlo usando el método where().
var evenNumbers = numbers.where((number) => number.isEven);
En este ejemplo,
numbers contiene un Iterable con múltiples valores int, y
where() encuentra todos los números que son pares.
La salida de where() es otro Iterable,
y puedes usarlo como tal para iterar sobre él o
aplicar otros métodos de Iterable.
En el siguiente ejemplo, la salida de where()
se utiliza directamente dentro del bucle for-in.
var evenNumbers = numbers.where((number) => number.isEven);
for (final number in evenNumbers) {
print('$number is even');
}
Ejemplo: Usar where()
#Ejecuta este ejemplo para ver cómo se puede usar where() junto con otros
métodos como any().
En este ejemplo, where() se usa para encontrar todos los números que son pares, luego
any() se usa para verificar si los resultados contienen un número negativo.
Más adelante en el ejemplo, se vuelve a usar where() para
encontrar todos los números mayores que 1000.
Como no hay ninguno, el resultado es un Iterable vacío.
Ejemplo: Usar takeWhile
#Los métodos takeWhile() y skipWhile() también pueden
ayudarte a filtrar elementos de un Iterable.
Ejecuta este ejemplo para ver cómo takeWhile() y skipWhile() pueden
dividir un Iterable que contiene números.
En este ejemplo, takeWhile() devuelve un Iterable que
contiene todos los elementos antes de aquel que
cumple con el predicado.
Por otro lado, skipWhile() devuelve un Iterable
que contiene todos los elementos a partir de e incluyendo el primero
que no cumple con el predicado.
Después de ejecutar el ejemplo,
cambia takeWhile() para tomar elementos hasta
que llegue al primer número negativo.
var numbersUntilNegative = numbers.takeWhile(
(number) => !number.isNegative,
);
Ten en cuenta que la condición number.isNegative se niega con !.
Ejercicio: Filtrar elementos de una lista
#El siguiente ejercicio ofrece práctica en el uso del método where() con
la clase User del ejercicio anterior.
Usa where() para implementar dos funciones:
-
Part 1: Implement
filterOutUnder21().- Devuelve un
Iterableque contenga a todos los usuarios de 21 años o más.
- Devuelve un
-
Part 2: Implement
findShortNamed().- Devuelve un
Iterableque contenga a todos los usuarios con nombres de longitud 3 o menos.
- Devuelve un
Pista
Recuerda aprovechar el método where de la clase Iterable.
Para obtener ayuda y ver ejemplos sobre el uso de where, consulta la
discusión anterior sobre él.
Solución
Iterable<User> filterOutUnder21(Iterable<User> users) {
return users.where((user) => user.age >= 21);
}
Iterable<User> findShortNamed(Iterable<User> users) {
return users.where((user) => user.name.length <= 3);
}
Mapeo
#Mapear Iterables con el método map() te permite
aplicar una función sobre cada uno de los elementos,
reemplazando cada elemento por uno nuevo.
Iterable<int> output = numbers.map((number) => number * 10);
En este ejemplo, cada elemento del Iterable de números se multiplica por 10.
También puedes usar map()
para transformar un elemento en un objeto diferente—por ejemplo,
para convertir todos los int a String,
como puedes ver en el siguiente ejemplo:
Iterable<String> output = numbers.map((number) => number.toString());
Ejemplo: Usar map para cambiar elementos
#Ejecuta este ejemplo para ver cómo usar map() para
multiplicar todos los elementos de un Iterable por 2.
¿Cuál crees que será la salida?
Ejercicio: Mapear a un tipo diferente
#En el ejemplo anterior, multiplicaste los elementos de un Iterable por 2.
Tanto la entrada como la salida de esa operación fueron un Iterable de
int.
En este ejercicio, tu código toma un Iterable de User,
y necesitas devolver un Iterable que
contenga cadenas con el nombre y la edad de cada usuario.
Cada cadena en el Iterable debe seguir este formato:
'{name} is {age}'—por ejemplo, 'Alice is 21'.
Pista
Recuerda aprovechar el método map de la clase Iterable.
Para obtener ayuda y ver ejemplos utilizando map, consulta la
discusión anterior sobre él.
Para concatenar múltiples valores en una sola cadena, considera usar la interpolación de cadenas.
Solución
Iterable<String> getNameAndAges(Iterable<User> users) {
return users.map((user) => '${user.name} is ${user.age}');
}
Ejercicio: Poniéndolo todo junto
#Es hora de practicar lo que aprendiste, en un ejercicio final.
Este ejercicio proporciona la clase EmailAddress,
la cual tiene un constructor que toma un string.
Otra función proporcionada es isValidEmailAddress(),
la cual comprueba si una dirección de correo electrónico es válida.
| Constructor/función | Firma de tipo | Descripción |
|---|---|---|
| EmailAddress() | EmailAddress(String address) |
Crea un EmailAddress para la dirección especificada. |
| isValidEmailAddress() | bool isValidEmailAddress(EmailAddress) |
Devuelve true si la EmailAddress proporcionada es válida. |
Escribe el siguiente código:
Parte 1: Implementar parseEmailAddresses().
- Escribe la función
parseEmailAddresses(), la cual toma unIterable<String>que contiene direcciones de correo electrónico, y devuelve unIterable<EmailAddress>. - Usa el método
map()para mapear de unStringaEmailAddress. - Crea los objetos
EmailAddressusando el constructorEmailAddress(String).
Parte 2: Implementar anyInvalidEmailAddress().
- Escribe la función
anyInvalidEmailAddress(), la cual toma unIterable<EmailAddress>y devuelvetruesi algunaEmailAddressen elIterableno es válida. - Usa el método
any()junto con la función proporcionadaisValidEmailAddress().
Parte 3: Implementar validEmailAddresses().
- Escribe la función
validEmailAddresses(), la cual toma unIterable<EmailAddress>y devuelve otroIterable<EmailAddress>que contiene solo direcciones válidas. - Usa el método
where()para filtrar elIterable<EmailAddress>. - Usa la función proporcionada
isValidEmailAddress()para evaluar si unaEmailAddresses válida.
Solución
Iterable<EmailAddress> parseEmailAddresses(Iterable<String> strings) {
return strings.map((s) => EmailAddress(s));
}
bool anyInvalidEmailAddress(Iterable<EmailAddress> emails) {
return emails.any((email) => !isValidEmailAddress(email));
}
Iterable<EmailAddress> validEmailAddresses(Iterable<EmailAddress> emails) {
return emails.where((email) => isValidEmailAddress(email));
}
Qué sigue
#¡Felicitaciones, has terminado el tutorial! Si quieres aprender más, aquí hay algunas sugerencias sobre dónde ir a continuación:
- Juega con DartPad.
- Lee la referencia de la API de Iterable para aprender sobre métodos que este tutorial no cubre.
A menos que se indique lo contrario, la documentación de este sitio refleja Dart 3.12.2. Página actualizada por última vez el 02-02-2026. Ver fuente oreportar un problema.