2013-12-10 2 views
3

Есть ли способ «перетасовать» вверх Iterable (или Sequence), чтобы элементы упорядочивались случайным образом, как и Java Collections.shuffle()? Я просмотрел документы API для Iterable, Collection и Sequence, но ничего не нашел. (Примечание стороны: ceylon.language::shuffle смешения называется)Цейлонский эквивалент Collections.shuffle()

Я мог бы реализовать себя перетасовать я полагаю, но я занят тем, чтобы быть ленивым :-)

ответ

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

Да, я подумал об этом после того, как я лег спать - здесь лучше. – Max