【问题标题】:Ceylon equivalent of Collections.shuffle()锡兰相当于 Collections.shuffle()
【发布时间】:2013-12-10 05:14:35
【问题描述】:

有没有办法将Iterable(或Sequence)“洗牌”,以便随后随机排序元素,类似于Java 的Collections.shuffle()?我查看了 IterableCollectionSequence 的 API 文档,但没有找到任何相关内容。 (旁注:ceylon.language::shuffle 名称容易混淆)

我想我可以自己实现洗牌,但我正忙着偷懒:-)

【问题讨论】:

    标签: ceylon


    【解决方案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;
            }
        };
    };
    

    【讨论】:

    • 感谢 gdejohn;如果有一个 Collections 或 CollectionUtil 类的库,那就太好了。我想我必须自己开始一个;)
    • FTR,我几天前实现了ceylon.collection.ArrayList。它将在下一个版本中。
    【解决方案2】:

    SDK 现在包含模块 ceylon.randomrandomize 函数:

    List&lt;Elements&gt; randomize&lt;Elements&gt;({Elements*} elements)

    【讨论】:

      【解决方案3】:

      我最终实现了自己的,基于最后的“由内而外”算法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 ,你大概可以猜到它的实现。

      【讨论】:

      • 使用LinkedList 是有问题的,因为将元素设置在特定索引处会在线性时间内运行。
      • 是的,我睡觉后就想到了这一点——数组在这里更好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多