I have an array of Objects for a quiz like so.
[
{
answer: "Patience"
question: "Name a GNR song..."
questionId: 13
questiontype: "text"
userId: 1
},
{
answer: "ABC"
question: "Select three MJ songs..."
questionId: 14
questiontype: "checkbox"
userId: 1
},
{
answer: "Thriller"
question: "Name three MJ songs..."
questionId: 14
questiontype: "checkbox"
userId: 1
}
]
What I am trying to do is display them on a page. So at the moment I am doing something like this
{quizData.map((item, index) => {
return (
<div key={index}>
<Col xs={12}>
<p className="text-start quiz-text">
<strong>
Question {item.question}
</strong>
</p>
</Col>
<Col xs={12}>
<p className="text-start argent c-font quiz-text">{item.answer}</p>
</Col>
</div>
);
})}
The problem is that this will display a new question row for each answer. So for the data above, I see something like this
Name a GNR song
Patience
Select 3 MJ songs
ABC
Select 3 MJ songs
Thriller
What I am trying to do is have only one question, but if that question has multiple answers, display these as part of that question. So the above would be something like
Name a GNR song
Patience
Select 3 MJ songs
ABC
Thriller
I presume I have to match the questionId somehow, but not sure how I can achieve this within my map?
Any advice appreciated.
Thanks
What you are trying to do is group each object of the array by questionId. So in order to do that, you can implement a vanilla version of groupBy() as mentioned in this answer by the following way
const groupBy = (list, keyGetter) => {
const map = new Map();
list.forEach((item) => {
const key = keyGetter(item);
const collection = map.get(key);
if (!collection) {
map.set(key, [item]);
} else {
collection.push(item);
}
});
return map;
}
After that you can simply use it as
// list of your question objects
var questions = [
{
answer: "Patience",
question: "Name a GNR song...",
questionId: 13,
questiontype: "text",
userId: 1,
},
{
answer: "ABC",
question: "Select three MJ songs...",
questionId: 14,
questiontype: "checkbox",
userId: 1,
},
{
answer: "Thriller",
question: "Name three MJ songs...",
questionId: 14,
questiontype: "checkbox",
userId: 1,
}
];
// groupBy function here shall return a Map object having questionId as key and
// list of objects having that questionId as value as specified in callback passed in
const myMap = groupBy(questions, x => x.questionId)
// Now you can simply iterate over the myMap object by using forEach
myMap.forEach(
group => { // group is the list of objects having same questionId
console.log(group[0].question);
group.map( // you can simply map your group like this
object => console.log(" ", object.answer)
)
}
)
// OUTPUT:
// Name a GNR song...
// Patience
// Select three MJ songs...
// ABC
// Thriller
You can first get unique question IDs into an array as follows using Map Constructor:
var uniqueQIDs = [...new Map(data.map(obj => [obj.questionId, obj])).values()].map(obj => obj.questionId);
Then you can loop on each question ID and filter your original data based on that as follows:
{uniqueQIDs.map((qID, index) => {
return (
<div key={index}>
<Col xs={12}>
<p className="text-start quiz-text">
<strong>
Question {qID}
</strong>
</p>
</Col>
<Col xs={12}>
{quizData.filter(obj => obj.questionId === qID).map(obj => {
return <p>{ obj.answer }</p>
})}
</Col>
</div>
);
})}
You can use array.filter() or for loop to modify the array berfore implementation . You have to make right array before implementing in map in jsx