Is there a way to "shuffle" up an Iterable
(or Sequence
), such that elements are subsequently ordered randomly, similar to Java's Collections.shuffle()
? I've looked in the API docs for Iterable
, Collection
, and Sequence
, but haven't found anything relevant. (Side note: ceylon.language::shuffle
is confusingly named)
I could implement a shuffle myself I suppose, but I'm busy trying to be lazy :-)
I also went looking for this and couldn't find it. Here's an implementation:
import ceylon.collection {ArrayList}
import ceylon.math.float {random}
"Don't interleave multiple iterators!"
Iterable<Element, Absent> shuffle<Element, Absent>(Iterable<Element, Absent> elements)
given Absent satisfies Null => object satisfies Iterable<Element, Absent> {
value list = ArrayList{elements = elements;};
iterator() => object satisfies Iterator<Element> {
variable value index = list.size;
shared actual Element|Finished next() {
value randomIndex = (random() * index--).integer;
if (exists element = list[index]) {
assert (exists randomElement = list[randomIndex]);
list.set(index, randomElement);
list.set(randomIndex, element);
return randomElement;
}
return finished;
}
};
};