juju
juju

Reputation: 326

How to select a few random id values from an array based on a matching argument?

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

Answers (7)

Azeem Aslam
Azeem Aslam

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

Jaffer
Jaffer

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

jo_va
jo_va

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

brk
brk

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

amazonic
amazonic

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

natsuozawa
natsuozawa

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

faizulhaque
faizulhaque

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

Related Questions