Count redundancy of answers in array - javascript

I have an array of objects like so
[
{_id: "5ca8b8ca0f1b2f54646ded9a", question: "Do you like it?", answer: "yes"},
{_id: "5ca8b8ca0f1b2f54646ded99", question: "Do you like it?", answer: "no"},
{_id: "5ca8b8f80f1b2f54646deda1", question: "Where are you?", answer: "home"},
{_id: "5ca8b8f80f1b2f54646deda0", question: "Where are you?", answer: "home"}
]
and I want it to be reproduced like the following:
[
{
"question": "Do you like it?",
"answers": [{"answer": "yes", "count": 1}, {"answer": "no", "count": 1}]
},
{
"question": "Where are you?",
"answers": [{"answer": "home", "count": 2}]
}
]
I have tried to solve this but i couldn't so any help would be much appreciated. Thank you

We can use Array.find to find the question-answer pair then add a new question-answer pair object if the pair is not existing or update the existing question-answer pair object.
If the question exits but the answer doesn't then simply add the new answer in the answers array.
If both the question and answer exists then increment the answer count property by 1.
If the question itself is missing then add a new object with the question property and answers property and set the count to 1.
Then finally use Array.reduce to accumulate the objects into an array.
const data = [
{_id: "5ca8b8ca0f1b2f54646ded9a", question: "Do you like it ?", answer: "yes"},
{_id: "5ca8b8ca0f1b2f54646ded99", question: "Do you like it ?", answer: "no"},
{_id: "5ca8b8f80f1b2f54646deda1", question: "Where are you ?", answer: "home"},
{_id: "5ca8b8f80f1b2f54646deda0", question: "Where are you ?", answer: "home"}
];
const res = data.reduce((acc, {question, answer}) => {
qFound = acc.find(qa => qa.question === question);
if(qFound){
ansFound = qFound.answers.find(ans => ans.answer === answer);
if(ansFound){
ansFound.count = ansFound.count + 1;
}else{
qFound.answers.push({answer, count:1});
}
}else{
acc.push({
question,
answers: [].concat({answer, count: 1})
});
}
return acc;
},[]);
console.log(res);

use reduce to create objects grouped by question and answer values and then later to discard the keys use Object.values()
const input = [
{_id: "5ca8b8ca0f1b2f54646ded9a", question: "Do you like it ?", answer: "yes"},
{_id: "5ca8b8ca0f1b2f54646ded99", question: "Do you like it ?", answer: "no"},
{_id: "5ca8b8f80f1b2f54646deda1", question: "Where are you ?", answer: "home"},
{_id: "5ca8b8f80f1b2f54646deda0", question: "Where are you ?", answer: "home"}
];
const groupByQuestionAndAnswers = Object.values(input.reduce((accu, {question, answer}) => {
if(!accu[question])
accu[question] = {question};
if(!accu[question][answer])
accu[question][answer] = {answer, count: 0};
accu[question][answer].count += 1;
return accu;
}, {}));
const output = groupByQuestionAndAnswers.map(({question, ...res}) => {
return {question, answers: Object.values(res)};
});
console.log(output);

Related

Dynamically update Array of objects with Mongoose

I have documents in my collection that look like this
let obj = {
email: hello#gmail.com,
deckName: hello,
data: [
{question: question1,
answer: answer1,
openHistory: ['12.06.22', '13.08.22'] //=> goal: []
},
{question: question2,
answer: answer2,
openHistory: ['14.05.22', '18.03.22'] //=> goal: []
},
]
}
I would like to filter all the documents for a specific email and set the openHistory to an empty array.
My try:
const Deck = require('../server/models/deck');
const deleteHistory = await Deck.updateMany({email:email}).data.forEach(x=>x.openHistory === [])
Thanks for reading!

How do we access the property of the object without calling object.property?

I'm pretty new to programming in general so this may be a very basic question.
Also English isn't my native language, my appologies if I don't express myself very well.
const questions = [{
question: "what is 2 + 2 ?",
answer: [{
text: "4",
correct: true
}];
]
function showQuestion(question) {
questionElement.innerText = question.question
}
I'm having trouble understanding, how do we access the question property of the object questions ("what is 2 + 2 ?") without calling its object.property(questions.question) but instead use parameter.property(question.question)?
const questions = [{
question: "what is 2 + 2 ?",
answer: [{
text: "4",
correct: true
}]
},
{
question: "what is 8 + 2 ?",
answer: [{
text: "10",
correct: true
}]
},
{
question: "what is 8 - 4 ?",
answer: [{
text: "4",
correct: true
}]
}
]
function showQuestion(id) {
// questionElement.innerText = question.question
console.log('question:'+ questions[id].question)
}
var id = Math.floor(Math.random() * questions.length)
showQuestion(id)
questions is an array, presumably containing multiple objects like the one you showed.
You call the function like this:
var i = Math.floor(Math.random() * questions.length); // Get random array index
showQuestion(questions[i]);
When you do this, the selected array element becomes the value of question in the function. You can then access its properties with question.propertyname.
If you still don't understand, you need to review your learning material, the section that explains function calling.
Another approach you you could use is a mixture of object destructuring and array destructuring to access object and array properties without explicitly specifying an index or using obj.prop. For example:
const questions = [{
question: "what is 2 + 2 ?",
answer: [{
text: "4",
correct: true
}]
}];
const [{
question,
answer
}] = questions;
const [{
text,
correct
}] = answer;
console.log(`${question}: ${text}`);

Stringify in objects JSON inside a object JSON

This is my object JSON:
var myJSon = {
"Student": "name",
"Answers":{
"Answer1": {
"question": "question",
"answer": "black",
"time": "00:02:30",
"number_tentatives": "1"
},
"Answer2": {
"question": "question",
"answer": "black",
"time": "00:02:30",
"number_tentatives": "2"
}
}
};
I need to fill in the object "Answer1" or "Answer2". I tried
myJSon.Respostas = JSON.stringify("One","hello","00:03:22","1");
But this results in {Student":"\"name\"","Answers":"\"oi\"}
What I would like is {"Student": "\"name\"", "Answers": {"Answer1": {"question": "One", "answer": "hello" ,"time":"00:03:22" ,"number_tentatives": "1"}, "
If you have an object containing multiple answers, it should be an array or map of answers.
Let's think of your object's initial state as this:
var myJson = {student: 'Student Name', answers: []};
So then you could start filling the answers array like:
myJson.answers.push({question: 'q', answer: 'a', time: 1, number_tentatives: 1});
If you'd now access myJson.answers it would be an array with one answer in it.
If you still think the way to go would be objects (so a 'key' is assigned to each answer), you would do this, instead of push:
myJson.answers['answer1'] = {question: 'q', answer: 'a', time: 1, number_tentatives: 1};
If you want to add additional data, then you could try this:
myJSon.Answers.Answer3 ={"question":"One","answer":"hello","time":"00:03:22","number_tentatives":"1"};
then test it like
console.log(JSON.stringify(myJSon));

unable to access object property through bracket variable notation

I am attempting to access one of the object propertie through a bracket notation, but I can not figure out why it is not working. As always, Your help is greatly appreciated!
js:
var dude = [
{
question1: "What is dude's favourite food?",
choices1: ["Pizza", "Pasta", "Chips", "Ice cream"],
answer1: 1
},
{
question2: "What was dude's first ever job?",
choices2: ["Staples", "Vodafone", "Costa", "Post office"],
answer2: 0
},
]
var counter = 1;
var currentQues = "question"+counter;
console.log(dude[currentQues]);
The console returns "undefined". Is this because it can not access a property through a variable(currentQues), which essentially holds another variable(counter)?
As always, your help is greatly appreciated. I am just a beginner looking to advance.
dude refers to an array of objects. You're trying to access question1 on dude, but you need to access it on dude[0]:
console.log(dude[0][currentQues]);
// -------------^^^
Live Example:
var dude = [
{
question1: "What is dude's favourite food?",
choices1: ["Pizza", "Pasta", "Chips", "Ice cream"],
answer1: 1
},
{
question2: "What was dude's first ever job?",
choices2: ["Staples", "Vodafone", "Costa", "Post office"],
answer2: 0
},
]
var counter = 1;
var currentQues = "question"+counter;
console.log(dude[0][currentQues]);
I would strongly recommend reconsidering that data structure. The names of the properties of the objects should be the same for all the objects, with just their position in the array differentiating them:
var dude = [{
question: "What is dude's favourite food?",
choices: ["Pizza", "Pasta", "Chips", "Ice cream"],
answer: 1
},
{
question: "What was dude's first ever job?",
choices: ["Staples", "Vodafone", "Costa", "Post office"],
answer: 0
},
]
dude.forEach(function(entry, index) {
var num = index + 1;
console.log("Question #" + num + ": " + entry.question);
});
You need to take the index of the array as well.
var dude = [{ question1: "What is dude's favourite food?", choices1: ["Pizza", "Pasta", "Chips", "Ice cream"], answer1: 1 }, { question2: "What was dude's first ever job?", choices2: ["Staples", "Vodafone", "Costa", "Post office"], answer2: 0 }],
counter = 1;
currentQues = "question" + counter;
console.log(dude[counter - 1][currentQues]);
// ^^^^^^^^^^^

How do I dynamically add objects to an object's property?

I am building a questionnaire and the questions can have multiple answers and I need to build an array of the question and answers such as:
{
question: 'question',
answer: {id: 1, answers: 'answer 1'},
{id: 2, answer: 'answer 2'}
}
I need to show a summary of the questions and the answers that the user chose.
For example: Question: Which of these states have you lived in?
answers: Alabama, Alaska, New Jersey, Rhode Island.
The resulting object could be:
{
question: 'Which of these states have you lived in?',
answer: {id: 1, answer: 'Alaska'},
{id: 3, answer: 'Rhode Island'}
}
How do I go about dynamically adding the answers while only having the question show up once?
I tried:
var questionAnswerObject = [];
angular.forEach(answersObject, function(value, key){
questionAnswerObject.push({
question: question.question,
answer: value.answer
});
});
But of course it shows the question twice.
Your missing something very important: you need answers to be an array (or an object), containing all the answers. You can't assign multiple objects to a value the way you are trying to do - they need to be wrapped somehow.
So, for example, your answer object might look like this instead:
var answerObject = {
question: 'My Question',
answers: [
{id: 1, answer: 'first answer'},
{id: 2, answer: 'second answer'}
]
}
Or, you could just make answers a map of the question ids like this:
var answerObject = {
question: 'My Question',
answers: {
1: 'first answer',
2: 'second answer'
}
}
To add an answer in the first example, simply do:
answerObject.answers.push( {id: 3, answer: 'new answer'} );
To add an answer in the second example, simply do:
answerObject.answers[3] = 'new answer';
What I think of you mean your final object to be like this question and array of answers
var arrayObjQuestions = [{
question: 'question',
answer: [{id: 1, answers: 'answer 1'},
{id: 2, answer: 'answer 2'}]
},...];
so if loop throw questions you have and add answer as follow
arrayObjQuestions[0].answer.push({id:1, answer: "answer 1"});
arrayObjQuestions[0].answer.push({id:2, answer: "answer 2"});
arrayObjQuestions[0].answer.push({id:3, answer: "answer 3"});
The best way to achieve this, use:
var questionAnswerObject = {};
var answers = [];
answers.push({id:1, answer: 'Alaska'});
answers.push({id:3, answer: 'Rhode Island'});
questionAnswerObject["question"] = 'Which of these states have you lived in?';
questionAnswerObject["answer"] = answers ;

Categories