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

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 ;

Related

Why is .push() method giving duplicates

{
category: 'Music',
id: '625064c2e12f6dec240bdfcb',
correctAnswer: "Don't Leave Me This Way",
incorrectAnswers: [
'Ice Ice Baby',
'In-A-Gadda-Da-Vida',
'Rebirth of Slick (Cool Like Dat)'
],
question: 'What song did Thelma Houston have a hit with in 1976?',
tags: [ 'songs', 'one_hit_wonders', 'music' ],
type: 'Multiple Choice',
difficulty: 'hard',
regions: []
}
// Here is the response from the API...
const oldArray = quizData[number].incorrectAnswers;
oldArray.push(quizData[number].correctAnswer);
console.log(oldArray);
// Here i am pushing the correctAnswer into the incorrect Answer array but my console.log keeps repeating the correct answer data, Why is this happening? Am i pushing it wrong?
['An arrow', 'A lightning bolt', 'A bottle of wine', 'A Discus', 'A Discus', 'A Discus', 'A Discus', 'A Discus']
//Here is my console.log array.
// 'A Discus' keeps getting repeated 4 times, Same length of the present array, So the array has 7 values instead of just 3, What is going on?
use the spread operator to avoid duplications
console.log( [...new Set(oldArray)])
const list = ['Anemia', 'Heart Attack', 'Paralysis', 'Epilepsy', 'Epilepsy']
console.log( [...new Set(list)])

Filter multidimensional array with objects

With an array like the following, how can I filter objects based on the texts.id? For example if I wanted to return this very same array without the texts object reffering to the id 123 how would I go about it? I have access to the id I want to filter out and also the name of the object where its located. I have been trying to figure this out but I am not sure this is doable with the filter method only. Thanks in advance to anyone that helps.
[
0: Object {
name: 'Name 1',
texts[
0: Obj{
id: '123',
body: 'test message'
},
1: Obj{
id: '456',
body: 'test message 2'
}
]
},
1: Object {
name: 'Name 2',
texts[
0: Obj{
id: '789',
body: 'test message3'
},
1: Obj{
id: '101112',
body: 'test message 4'
}
]
}
]
It's not totally clear to me whether you want to remove the entire outer object where the texts array contains an object with a certain id (i.e: in your example, this would remove the whole object with name 'Name 1'), or if you just want to remove the object in the texts array which has a certain id (i.e: leaving the outer object, just removing the object in texts with id 123).
The former has been answered by #lissettdm above, but if it's the latter, you could do something like this:
const filter = "123";
entry.forEach(item => item.texts = item.texts.filter(text => text.id !== filter));
Yes, it is possible using Array.prototype.filter() and Array.prototype.find()
const entry = [{name: "Name 1",texts: [{id: "123",body: "test message"},{id: "456",body: "test message 2"}]},{name: "Name 2",texts: [{id: "789",body: "test message3"},{id: "101112",body: "test message 4"}]}];
const filter= "123";
const output = entry.filter(item => item.texts.find(text=> text.id===filter));
console.log(output);

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}`);

Count redundancy of answers in array

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);

Select a specific item from an array in a Handlebars template

If I have the following 2 arrays bound to a compiled Handlebars template:
questions: [
{id:1, text:'question1', answers: [
{id: 1, text:'answer1'},
{id: 2, text:'answer2'}
]},
{id:2, text:'question2', answers: [
{id: 1, text:'answer3'},
{id: 2, text:'answer4'}
]}
],
userAnswers: [
{questionId:1, answerId:2}
]
I would rather not change the data structure and need to do the following (pseudo-code):
for each (question in questions)
render question text
render user answer text
(note that there may be a question without an answer)
If I use 'each' in my Handlebars template:
{{#each question}}
Is there a way to get the answer id from the userAnswers object?
Then map this back to questions to get the text?
e.g. is there some kind of selector syntax such as:
{{../userAnswers[questionId=id].answerId}}

Categories