Ceylon相当于Collections.shuffle()

时间:2013-12-10 05:14:35

标签: ceylon

有没有办法“改变”Iterable(或Sequence),以便随后对元素进行随机排序,类似于Java的Collections.shuffle()?我查看过IterableCollectionSequence的API文档,但未发现任何相关内容。 (附注:ceylon.language::shuffle令人困惑地命名)

我想我可以自己实施一次洗牌,但我正忙着懒惰: - )

3 个答案:

答案 0 :(得分:1)

我也去寻找这个并找不到它。这是一个实现:

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;
        }
    };
};

答案 1 :(得分:1)

SDK现在包含具有ceylon.random功能的模块randomize

List<Elements> randomize<Elements>({Elements*} elements)

答案 2 :(得分:0)

基于最后一个“由内而外”的算法here,我最终实现了自己的算法。

[Element*] shuffle<Element>({Element*} input) {
    value newList = LinkedList<Element>();
    for(el in input){
        value j = math.randomInteger {lowerBound=0; upperBound=newList.size; inclusiveUpperBound=true;};
        if(j == newList.size){
            newList.add(el);
        } else {
            value elementToMove = newList[j];
            assert(exists elementToMove);
            newList.add(elementToMove);
            newList.set(j, el);
        }
    }
    return newList.sequence;
}

尚未验证正确性。我也实现了math.randomInteger,你可以猜测它的实现。