shuffle

Devuelve una nueva lista con los elementos barajados — pasa una semilla para obtener un resultado reproducible.

List<T> shuffle<T>(Iterable<T> iterable, [int? seed]) Future<List<T>> shuffleAsync<T>(FxAsyncIterable<T> iterable, [int? seed]) List<T> Iterable<T>.fxShuffle([int? seed]) // method Future<List<T>> FxAsyncIterable<T>.fxShuffle([int? seed]) // method

Lección

shuffle aplica un barajado de Fisher-Yates a los elementos de iterable y devuelve una List<T> totalmente nueva: la entrada nunca se muta. Si lo llamas sin semilla, usa Random de dart:math, así que cada llamada da un orden distinto, justo lo que esperas para una baraja de cartas o un cuestionario aleatorizado.

Si le pasas un seed de tipo int, shuffle cambia a un PRNG con semilla (un port a Dart del mismo generador estilo Mulberry32 que usa FxTS), de modo que la misma semilla produce siempre el mismo orden: en cualquier ejecución y en cualquier máquina. Ese determinismo es lo que hace útil el barajado con semilla para fixtures de test reproducibles, puzles de «reto diario» donde todo el mundo con la semilla de hoy ve la misma disposición, o repeticiones deterministas de una simulación aleatorizada.

shuffleAsync es el gemelo *Async: primero materializa el FxAsyncIterable (internamente con toListAsync) y luego baraja el resultado, así que un barajado asíncrono con semilla produce exactamente el mismo orden que su equivalente síncrono con la misma semilla.

Demo 1 · Determinismo con semilla

Misma semilla, mismo orden, siempre. Una semilla distinta da un orden distinto (pero igual de reproducible):

Demo 2 · shuffleAsync coincide con el orden síncrono, y no se pierde nada

La misma semilla da un orden idéntico tanto si la fuente es síncrona como asíncrona, y todos los elementos de la entrada siguen ahí, solo que reordenados:

La forma con método

xs.fxShuffle(seed) es shuffle(xs, seed), y sobre un FxAsyncIterable ese mismo nombre es shuffleAsync.

No se llama shuffle, y no es una cuestión de estilo. List.shuffle ya existe en dart:core y baraja en el sitio, devolviendo void. Un miembro de instancia siempre gana a una extensión, así que con un List como receptor se llamaría en silencio al equivocado; el prefijo hace imposible confundirlos.

final a = [1, 2, 3].fxShuffle(42);   // a new List, seeded
final b = [1, 2, 3]..shuffle();      // dart:core, in place, void

Pruébalo tú

Ejercicio: dale una semilla a este orden de turnos para que sea reproducible entre reinicios de la app en lugar de aleatorio cada vez.

Relacionado: throttle — limitación de frecuencia para callbacks · debounce — limitación que espera a que haya calma · toAsync — eleva una lista para usarla con shuffleAsync · sort — el instinto contrario: orden determinista