简体   繁体   English

如何从Javascript中的嵌套数组中获取10个非重复随机对象?

[英]How to get 10 non-repeating random objects from nested array in Javascript?

I have an object like this: 我有一个这样的对象:

var database = [
  {
    category: 'CPUs',
    id: 1,
    products: [Product, Product, Product] //Product is an object
  },
  {
    category: 'GPUs',
    id: 2,
    products: [Product, Product]
  }      
];

and so on.. 等等..

I'd like to get 10 random products in total, non-repeating. 我想总共获得10个随机产品,且不重复。 There can be more than one from the same category, as long as they are different products. 只要是不同的产品,同一类别中可以有多个。 How can I do this? 我怎样才能做到这一点? I tried this: 我尝试了这个:

function getRandomFromObject(){
    var productsCollected = [];

    while(productsCollected.length < 10){
        var randomCategory = database[Math.floor(Math.random()*database.length)];
        var randomProduct = randomCategory.products[Math.floor(Math.random()*randomCategory.products.length)];
        productsCollected.push(randomProduct);
    }
    return productsCollected;
}

Things become easier if you first concatenate all the products into one array, then shuffle that array and finally take the first 10 from that: 如果首先将所有产品连接到一个阵列中,然后将其随机组合,最后从中取出前10个,则事情会变得更容易:

 function shuffle(a) { for (let i = a.length; i; i--) { let j = Math.floor(Math.random() * i); [a[i - 1], a[j]] = [a[j], a[i - 1]]; } return a; } function getRandomFromObject(count){ return shuffle([].concat(...database.map(o => o.products))).slice(0, count); } var database = [ { category: 'CPUs', id: 1, products: ['a', 'b', 'c'] //Product is an object }, { category: 'GPUs', id: 2, products: ['d', 'e'] }, { category: 'GPUs', id: 3, products: ['f', 'g', 'h', 'i', 'j'] } ]; console.log(getRandomFromObject(10).join(',')); 

Addendum: If you can have the same Product object occurring in different categories, then apply a Set to the concatenated array, so to eliminate these duplicates: 附录:如果可以使同一Product对象出现在不同的类别中,则将Set应用于连接的数组,以便消除这些重复项:

return shuffle([...new Set([].concat(...database.map(o => o.products)))]).slice(0, count);

ES5 Code ES5代码

As you asked in comments for ES5, and the need to consider products with the same ISBN property as the same products, here is the code for that: 正如您在对ES5的评论中所问的那样,以及需要考虑具有与相同产品相同的ISBN属性的产品,以下是该代码:

 function shuffle(a) { for (var i = a.length; i; i--) { var j = Math.floor(Math.random() * i); var temp = a[i - 1]; a[i - 1] = a[j]; a[j] = temp; } return a; } function getRandomFromObject(count){ var uniq = {}; // Unique list of products, keyed by ISBN database.forEach(function (o) { o.products.forEach(function (product) { uniq[product.isbn] = product; }); }); var products = []; for (product in uniq) { products.push(uniq[product]); } return shuffle(products).slice(0, count); } var database = [ { category: 'CPUs', id: 1, products: [{ isbn: 'a' }, { isbn: 'b' }, { isbn: 'c' }] //Product is an object }, { category: 'GPUs', id: 2, products: [{ isbn: 'd' }, { isbn: 'a' }, { isbn: 'j' }] // has same isbn as in CPUs }, { category: 'Others', id: 3, products: [{ isbn: 'e' }, { isbn: 'f' }, { isbn: 'g' }, { isbn: 'h' }, { isbn: 'i' }] } ]; console.log(getRandomFromObject(10)); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM