2013-12-10 64 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