如何从es6 Map或Set中获取随机项

bac*_*ces 10 dictionary set ecmascript-6

我有一个项目使用我想要移动到es6集或地图的对象数组.

我需要快速从它们中获取一个随机项(对于我当前的数组来说显然是微不足道的).我该怎么做?

jfr*_*d00 12

地图和集合不适合随机访问.它们是有序的,它们的长度是已知的,但它们没有被索引用于订单索引的访问.因此,要在Map或Set中获取第N个项目,您必须遍历它才能找到该项目.

从Set或Map中获取随机项的简单方法是获取整个键/项列表,然后选择一个随机项.

// get random item from a Set
function getRandomItem(set) {
    let items = Array.from(set);
    return items[Math.floor(Math.random() * items.length)];
}
Run Code Online (Sandbox Code Playgroud)

您可以创建一个适用于Set和Map的版本,如下所示:

// returns random key from Set or Map
function getRandomKey(collection) {
    let keys = Array.from(collection.keys());
    return keys[Math.floor(Math.random() * keys.length)];
}
Run Code Online (Sandbox Code Playgroud)

这显然不适合使用大型Set或Map,因为它必须迭代所有键并构建临时数组以便选择随机数组.


由于Map和Set都具有已知大小,您还可以选择纯粹基于.size属性的随机索引,然后您可以迭代Map或Set,直到达到所需的第N个项目.对于大型集合,这可能会更快一些,并且会避免以更多代码为代价创建临时密钥数组,尽管平均而言它仍然与集合的大小/ 2成比例.

// returns random key from Set or Map
function getRandomKey(collection) {
    let index = Math.floor(Math.random() * collection.size);
    let cntr = 0;
    for (let key of collection.keys()) {
        if (cntr++ === index) {
            return key;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*han 7

这是集合的简短答案:

const getRandomItem = set => [...set][Math.floor(Math.random()*set.size)]
Run Code Online (Sandbox Code Playgroud)


all*_*llx 5

上面的答案有一个简短的 ES6+ 版本:

const getRandomItem = iterable => iterable.get([...iterable.keys()][Math.floor(Math.random() * iterable.size)])
Run Code Online (Sandbox Code Playgroud)

适用于 Maps 和 Sets(其中 keys() 是 value() 方法的别名)