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)
这是集合的简短答案:
const getRandomItem = set => [...set][Math.floor(Math.random()*set.size)]
Run Code Online (Sandbox Code Playgroud)
上面的答案有一个简短的 ES6+ 版本:
const getRandomItem = iterable => iterable.get([...iterable.keys()][Math.floor(Math.random() * iterable.size)])
Run Code Online (Sandbox Code Playgroud)
适用于 Maps 和 Sets(其中 keys() 是 value() 方法的别名)