shuffle

Returns a new list with elements in shuffled order — pass a seed for a reproducible result.

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

Lecture

shuffle runs a Fisher-Yates shuffle over the elements of iterable and returns a brand-new List<T> — the input is never mutated. Called with no seed, it uses dart:math's Random, so every call gives a different order, exactly as you'd expect for something like a card deck or a randomized quiz.

Pass an int seed and shuffle switches to a seeded PRNG (a Dart port of the same Mulberry32-style generator FxTS uses), so the same seed always produces the same order — on any run, on any machine. That determinism is what makes seeded shuffling useful for things like reproducible test fixtures, "daily challenge" puzzles where everyone with today's seed sees the same layout, or deterministic replays of a randomized simulation.

shuffleAsync is the *Async twin: it materializes an FxAsyncIterable first (via toListAsync internally) and then shuffles the result, so a seeded async shuffle produces the identical order to its sync counterpart given the same seed.

Demo 1 · Seeded determinism

Same seed, same order — every time. A different seed gives a different (but still reproducible) order:

Demo 2 · shuffleAsync matches the sync order, and nothing is lost

Same seed gives the identical order whether the source is sync or async — and every element from the input is still present, just reordered:

Method spelling

xs.fxShuffle(seed) is shuffle(xs, seed), and on an FxAsyncIterable the same name is shuffleAsync.

It is not called shuffle, and that is not a style choice. List.shuffle already exists in dart:core and shuffles in place, returning void. An instance member always beats an extension, so a List receiver would silently call the wrong one — the prefix makes the two impossible to confuse.

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

Try it yourself

Exercise: give this turn order a seed so it's reproducible across app restarts instead of random every time.

Related: throttle — rate-limiting for callbacks · debounce — wait-for-quiet rate limiting · toAsync — lifting a list for shuffleAsync · sort — the opposite instinct: deterministic order