2013-12-10 28 views

回答

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

由於gdejohn;如果有一個Collections或CollectionUtil類庫,它會很好。猜猜我必須自己開始;) – Max

+1

FTR,幾天前我實現了'ceylon.collection.ArrayList'。它將在下一個版本中發佈。 –

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,你可能會在實現時猜測它。

+0

使用「LinkedList」是有問題的,因爲在特定索引處設置元素會以線性時間運行。 – gdejohn

+0

是的,我睡覺後想到了這一點 - Array在這裏更好。 – Max