Iterable în Dart

Tipul de bază pentru orice colecție care poate fi parcursă element cu element: List, Set, cheile unui Map.

Sintaxă
abstract mixin class Iterable<E>

Iterable<E>.generate(int count, [E generator(int index)?])
const Iterable<E>.empty()

Ce face Iterable

Iterable<E> descrie o succesiune de elemente de tipul E care pot fi parcurse, în ordine, cu for-in. List, Set, map.keys și map.values sunt toate Iterable, deci au aceleași metode: map, where, fold, join, first și multe altele.

Multe metode (map, where, take, skip) sunt leneșe: nu calculează nimic pe loc, ci returnează un nou Iterable care calculează elementele abia când este parcurs. De aceea print pe un astfel de rezultat afișează elementele între paranteze rotunde, (1, 2, 3), nu între paranteze drepte ca o listă. Apelează toList() când ai nevoie de o listă.

Constructorul Iterable.generate(n, f) creează un iterable cu elementele f(0), f(1), …, f(n - 1); fără funcție, elementele sunt chiar numerele 0 … n – 1. Iterable.empty() creează un iterable fără niciun element.

Parametri

Parametru Descriere
count Pentru Iterable.generate: câte elemente are rezultatul.
generator Funcția care primește poziția (0, 1, 2, …) și returnează elementul. Dacă lipsește, elementul este chiar poziția.

Ce returnează

Un obiect Iterable. Elementele lui se calculează abia când îl parcurgi.

Exemple

Exemplul 1: Același cod pentru listă, mulțime și cheile unui map

Funcția afiseaza primește orice Iterable<String>, deci merge cu o listă, cu un set sau cu cheile unui map.

void afiseaza(String titlu, Iterable<String> elemente) {
  print('$titlu (${elemente.length}): ${elemente.join(', ')}');
}

void main() {
  final orase = ['Iași', 'Cluj', 'Brașov'];
  final culori = {'roșu', 'galben', 'albastru'};
  final populatie = {'Iași': 271692, 'Timișoara': 250849};

  afiseaza('Listă', orase);
  afiseaza('Set', culori);
  afiseaza('Chei', populatie.keys);
  for (final oras in populatie.keys) {
    print('$oras are ${populatie[oras]} locuitori');
  }
}

Rezultat

Listă (3): Iași, Cluj, Brașov
Set (3): roșu, galben, albastru
Chei (2): Iași, Timișoara
Iași are 271692 locuitori
Timișoara are 250849 locuitori

Exemplul 2: Iterable.generate și Iterable.empty

Rezultatul lui generate este leneș: print îl afișează cu paranteze rotunde. toList() îl transformă în listă.

void main() {
  final pozitii = Iterable<int>.generate(5);
  final patrate = Iterable.generate(5, (i) => i * i);
  const nimic = Iterable<String>.empty();

  print(pozitii);
  print(patrate);
  print(patrate.toList());
  print('gol: $nimic, isEmpty = ${nimic.isEmpty}');
}

Rezultat

(0, 1, 2, 3, 4)
(0, 1, 4, 9, 16)
[0, 1, 4, 9, 16]
gol: (), isEmpty = true

Exemplul 3: Calculul leneș: elementele se calculează la parcurgere

Funcția din map nu rulează când creezi dublate, ci abia în bucla for. Dacă parcurgi de două ori, se calculează de două ori.

void main() {
  final note = [7, 9, 10];
  final dublate = note.map((n) {
    print('  calculez $n');
    return n * 2;
  });
  print('Am creat iterable-ul, nimic calculat încă.');
  for (final d in dublate) {
    print('primit $d');
  }
}

Rezultat

Am creat iterable-ul, nimic calculat încă.
  calculez 7
primit 14
  calculez 9
primit 18
  calculez 10
primit 20

Greșeli frecvente

  • Te aștepți ca map sau where să modifice lista. Ele returnează un iterable nou și leneș; lista inițială rămâne neschimbată.
  • Folosești de mai multe ori un iterable leneș cu o funcție costisitoare sau cu efecte (afișări, numărători). Fiecare parcurgere recalculează totul; salvează rezultatul cu toList().

Comenzi înrudite

  • Iterable.map: Transformă fiecare element cu o funcție și returnează un iterable nou, leneș, cu rezultatele.
  • Iterable.where: Păstrează doar elementele care trec un test; whereType păstrează doar elementele de un anumit tip.
  • Iterable.toList: toList copiază elementele într-o listă nouă; toSet le copiază într-un set nou, fără duplicate.
  • List: Lista din Dart: elemente în ordine, accesate după poziție, care poate crește sau scădea.
  • Set: Colecție fără elemente duplicate: fiecare valoare apare o singură dată, iar căutarea este rapidă.
  • Iterator: Obiectul care parcurge un Iterable pas cu pas; for-in îl folosește în spate prin getter-ul iterator.