我有一个700个问题对象的数组,如下所示:
[
{
_id: "5ca3216579a592b0910f70d4"
question: "Who wrote Twilight series of novels?"
answer: "Stephenie Meyer"
category: "Art and Literature"
},
...
]
我还有一个由3个选定的问题类别组成的数组,如下所示:
["Art and Literature", "Music", "History"]
我基本上需要的是每个问题类别的4个随机问题。所以:
理想情况下,我认为将12个随机问题ID设置在基于这3个类别的新数组中会很好,所以我可以将它们发送到我的数据库。
怎么做?
const questions = [
{
_id: "5ca3216579a592b0910f70d4",
question: "Who wrote Twilight series of novels?",
answer: "Stephenie Meyer",
category: "Art and Literature",
}
]
const categories = ["Art and Literature", "Music", "History"];
const numberOfEachCategory = 2;
const randSelected = categories.map((category) => {
const filtered = questions.filter((obj) => obj.category === category).slice();
if(filtered.length > numberOfEachCategory) {
const randomArray = [];
for(let i = numberOfEachCategory; i > 0; i--) {
randomArray.push(...filtered.splice(Math.floor(Math.random() * filtered.length), 1));
}
return randomArray;
} else {
return filtered;
}
})
console.log(randSelected);
结果是数组数组。每个类别的每个内部数组
您应该首先为每个类别创建一个问题数组,以便随机选择。
const art = arr.filter(question => question.category === 'Art and Literature');
const music = arr.filter(question => question.category === 'Music');
const history = arr.filter(question => question.category === 'History');
现在,只需为每个类别数组随机选择四次项目。
const categoryArrays = [art, music, history];
const results = [] // to store the selected ids
for (i = 0, i < 3, i++) { // To iterate over the three categories
for (j = 0, j < 4, j++) { // To select four times
results.push(categoryArrays[i][Math.floor(Math.random() * categoryArrays[i].length)]._id);
}
}
这有几个步骤。首先,您需要过滤掉特定类别的项目列表。
const categories = ["Art and Literature", "Music", "History"];
for (let c of categories) {
const itemsOfCategory = items.filter(i => item.category === c);
}
然后,您将要从筛选列表中选择4个随机项并返回它们。把它放在它自己的功能中似乎是最好的。
const getRandomItems = (items, categories, numberOfItems) => {
const results = [];
for (let c of categories) {
const itemsOfCategory = items.filter(i => i.category === c);
const pickedItems = [];
for (let i = 0; i < numberOfItems; i += 1) {
pickedItems.push(Math.trunc(Math.random()*itemsOfCategory.length))
}
results.push(pickedItems)
}
return results;
}
然后,您可以传入项目列表,所需类别以及所需项目数。
const randomItems = getRandomItems(items, categories, 4);
您可以在map
数组上使用categories
,然后在回调中使用filter
来获取类别匹配的对象数组。在第一次迭代时,它将给出一个数组,其中类别为Art and Literature
,依此类推。然后运行另一个循环来生成4个随机数,并使用此随机数从过滤后的数组中获取一个随机问题。将该值存储在临时变量中并返回该值
let ques = [{
_id: "5ca3216579a592b0910f70d4"
question: "Who wrote Twilight series of novels?"
answer: "Stephenie Meyer"
category: "Art and Literature"
}]
let type = ["Art and Literature", "Music", "History"];
let randomQues = type.map(function(item) {
let quesArrays = []
let k = ques.filter(elem) {
return elem.category === item;
}) for (let i = 0; i < 4; i++) {
let rand = Math.floor(Math.random() * k.length);
quesArrays.push(rand)
}
return quesArrays;
})
您可以使用reduce()按类别对所有问题ID进行分组,然后从这些数组中选择N个随机项:
const categories = ['cat1', 'cat2', 'cat3'];
const questions = Array.from({ length: 10 }, (_, i) => (
{ _id: i, question: `question ${i}`, answer: `answer ${i}`, category: categories[Math.floor(Math.random() * categories.length)]})
);
function randomQuestions(questions, categories, n) {
// group the ids into arrays for each category asked
const idsByCategories = questions.reduce((acc, x) => {
if (categories.includes(x.category)) {
acc[x.category] = [...(acc[x.category] || []), x._id];
}
return acc;
}, {});
// pick a number of random ids for each category
return categories.map(cat => (idsByCategories[cat] || []).sort(() => 0.5 - Math.random()).slice(0, n));
}
console.log(JSON.stringify(randomQuestions(questions, ['cat1', 'cat3'], 2)));
console.log(questions);
随机数组选择代码采取from this answer。
使用shuffle函数来重新包含包含问题的数组,而不是仅通过匹配类别获得前4个结果。
这是伪代码:
let arrayOfQuestions =[];
let shuffledQuestions = _.shuffle(arrayOfQuestions); // _ is Lodash
let artAndLiteratureQuestions = _.find(shuffledQuestions, { category: 'Art and Literature' }
以同样的方式,您可以提取其他类别的问题。
您可以使用此逻辑将所有结果集中在所有类别的一个班轮中:)只需要使用您的支票更改过滤器检查。
let list = [1,1,1,1, 1, 1,1, 3, 2, 3, 4, 5, 6 ];
let options = [1, 3];
const result = options.map((val) => {
return list.filter(f => val === f ).map((v, i, ref) => {
if(i<=3)
return ref[parseInt(Math.random()*ref.length-i)]
}).slice(0, 3)
})
console.log(result);