Reputation: 326
I have an array of 700 question objects that look like this:
[
{
_id: "5ca3216579a592b0910f70d4"
question: "Who wrote Twilight series of novels?"
answer: "Stephenie Meyer"
category: "Art and Literature"
},
...
]
I also have an array of 3 selected question categories that look like this:
["Art and Literature", "Music", "History"]
What I basically need is 4 random questions of each question category. So:
Ideally I think it would be nice to have the 12 random question id's set in a new array based on these 3 categories so I could send them to my database.
How is this to be done?
Upvotes: 2
Views: 685
Reputation: 544
You may use this logic to get all results in one liner for all categories :) Just need to change filter check with your check.
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);
Upvotes: 0
Reputation: 2968
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);
Result is Array of Arrays. each inside array for each category
Upvotes: 1
Reputation: 13993
You could group all question ids by categories using reduce(), and then pick N random items from these arrays:
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);
The random array picking code was taken from this answer.
Upvotes: 2
Reputation: 50346
You can use map
on categories
array and then inside the callback use filter
to get an array of objects where category matches. On first iteration it will give an array where the category is Art and Literature
and so on. Then run another loop to get generate 4 random numbers and using this random number get a random question from filtered array.Store that value in a temporary variable and return that
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;
})
Upvotes: 2
Reputation: 356
There's a couple of steps to this. First you'll want to filter out a list of items for the specific category.
const categories = ["Art and Literature", "Music", "History"];
for (let c of categories) {
const itemsOfCategory = items.filter(i => item.category === c);
}
Then you'll want to pick 4 random items from the filtered list and return them. It seems nicest to put this in it's own function.
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;
}
You then pass in your list of items, the categories you want and how many items you want.
const randomItems = getRandomItems(items, categories, 4);
Upvotes: 2
Reputation: 660
You should first create an array of questions for each category to randomly select from.
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');
Now, just choose items randomly four times for each category array.
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);
}
}
Upvotes: 2
Reputation: 106
Use shuffle function to remdomize the array containing questions than just take first top 4 results by matching category.
Here is pseudo code:
let arrayOfQuestions =[];
let shuffledQuestions = _.shuffle(arrayOfQuestions); // _ is Lodash
let artAndLiteratureQuestions = _.find(shuffledQuestions, { category: 'Art and Literature' }
in the same way you can extract the others category questions.
Upvotes: 0