shuffle

원소 순서를 뒤섞은 새 리스트를 반환합니다 — 시드를 넘기면 결과를 재현할 수 있습니다.

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

강의

shuffleiterable의 원소에 Fisher-Yates 셔플을 적용해 완전히 새로운 List<T>를 반환합니다 — 입력은 절대 변경되지 않습니다. 시드 없이 호출하면 dart:mathRandom을 사용하므로 호출할 때마다 순서가 달라집니다. 카드 덱을 섞거나 퀴즈 문항을 무작위로 배치할 때 기대하는 그대로입니다.

int 타입의 seed를 넘기면 시드 기반 PRNG로 전환됩니다(FxTS가 쓰는 것과 같은 Mulberry32 계열 생성기를 Dart로 포팅했습니다). 그래서 같은 시드는 언제나 같은 순서를 만들어냅니다 — 어떤 실행에서든, 어떤 머신에서든 마찬가지입니다. 이 결정성 덕분에 시드 셔플은 재현 가능한 테스트 픽스처, 오늘의 시드를 가진 모두가 같은 배치를 보게 되는 "일일 챌린지" 퍼즐, 무작위 시뮬레이션의 결정적 리플레이 같은 곳에 유용합니다.

shuffleAsync*Async 짝입니다. 내부적으로 toListAsync를 통해 FxAsyncIterable을 먼저 구체화한 다음 그 결과를 섞기 때문에, 같은 시드를 주면 시드 기반 비동기 셔플은 동기 버전과 완전히 동일한 순서를 만들어냅니다.

데모 1 · 시드로 얻는 결정성

같은 시드라면 언제나 같은 순서입니다. 시드가 다르면 순서도 달라지지만, 그 순서 역시 재현 가능합니다:

데모 2 · shuffleAsync는 동기와 같은 순서를 내고, 원소는 하나도 잃지 않습니다

소스가 동기든 비동기든 같은 시드면 순서가 동일합니다 — 그리고 입력의 모든 원소는 순서만 바뀐 채 그대로 남아 있습니다:

메서드 표기

xs.fxShuffle(seed)shuffle(xs, seed)이고, FxAsyncIterable에서 같은 이름은 shuffleAsync입니다.

이름이 shuffle이 아닌 것은 취향 문제가 아닙니다. List.shuffle은 이미 dart:core에 있고, 제자리에서 섞고 void를 돌려줍니다. 인스턴스 멤버는 항상 확장을 이기므로 List를 수신자로 두면 조용히 엉뚱한 쪽이 불립니다 — 접두사가 둘을 헷갈릴 수 없게 만듭니다.

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

직접 해 보기

연습: 이 턴 순서에 시드를 주어, 매번 무작위로 바뀌는 대신 앱을 재시작해도 재현되도록 만들어 보세요.

관련 항목: throttle — 콜백에 대한 호출 빈도 제한 · debounce — 조용해질 때까지 기다리는 빈도 제한 · toAsync — shuffleAsync에 쓰도록 리스트를 끌어올리기 · sort — 정반대의 발상: 결정적인 순서