有沒有辦法「洗牌」Iterable
(或Sequence
),這樣的元素隨後隨機排序,類似於Java的Collections.shuffle()
?我查看了Iterable
,Collection
和Sequence
的API文檔,但未發現任何相關內容。 (附註:ceylon.language::shuffle
是容易混淆的名字命名)錫蘭當量Collections.shuffle()
我可以實現一個洗牌自己,我想,但我忙於偷懶:-)
有沒有辦法「洗牌」Iterable
(或Sequence
),這樣的元素隨後隨機排序,類似於Java的Collections.shuffle()
?我查看了Iterable
,Collection
和Sequence
的API文檔,但未發現任何相關內容。 (附註:ceylon.language::shuffle
是容易混淆的名字命名)錫蘭當量Collections.shuffle()
我可以實現一個洗牌自己,我想,但我忙於偷懶:-)
我也去尋找這一點,並不能找到它。這裏的一個實現:
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;
}
};
};
我最終實現了我自己的,基於最後一個「內外」算法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,你可能會在實現時猜測它。
該SDK現在包括模塊ceylon.random
與randomize
功能:
List<Elements> randomize<Elements>({Elements*} elements)
由於gdejohn;如果有一個Collections或CollectionUtil類庫,它會很好。猜猜我必須自己開始;) – Max
FTR,幾天前我實現了'ceylon.collection.ArrayList'。它將在下一個版本中發佈。 –