randomize<T> static method

List<T> randomize<T>(
  1. Iterable<Iterable<T>> root, {
  2. int? length,
  3. List<T> initial = const [],
  4. T converter(
    1. int index,
    2. T old
    )?,
})

Randomly selects elements from multiple lists while ensuring uniqueness.

Parameters:

  • root: A list of lists containing possible values.
  • length: The desired number of elements in the result.
  • initial: An optional list of initial values (default is empty).
  • converter: A function to modify selected items before adding them.

Example:

List<List<String>> root = [
  ['A', 'B', 'C'],
  ['D', 'E'],
  ['F', 'G', 'H']
];

List<String> result = randomize(root, 5);
// Possible output: ['B', 'D', 'F', 'C', 'E']

Implementation

static List<T> randomize<T>(
  Iterable<Iterable<T>> root, {
  int? length,
  List<T> initial = const [],
  T Function(int index, T old)? converter,
}) {
  if (root.isEmpty) return [];
  final total = root.map((e) => e.length).reduce((a, b) => a + b);
  length ??= total;
  final random = Random();
  List<T> randoms = [...initial];
  for (int i = 0; i < root.length; i++) {
    final items = root.elementAtOrNull(i);
    if (items == null || items.isEmpty) continue;
    int index = random.nextInt(items.length);
    final item = items.elementAtOrNull(index);
    if (item == null) continue;
    if (length <= total && randoms.contains(item)) continue;
    randoms.add(
      converter != null ? converter(randoms.length + 1, item) : item,
    );
  }
  if (randoms.length == length) return randoms;
  if (randoms.length > length) return randoms.take(length).toList();
  return randomize(
    root,
    length: length,
    initial: randoms,
    converter: converter,
  );
}