Hi I have been trying make this following array
[
{
"name": "Study",
"questions": [
{
"question": "Would you Love to learn about Java?",
"answer": "Yes"
}
]
},
{
"name": "Song",
"questions": [
{
"question": "Would you Love to learn about song?",
"answer": "Yes"
},
{
"question": "Would you Love to learn about rock?",
"answer": "No"
}
]
}
]
To this
[
{
"questions": [
{
"question": "Would you Love to learn about Java?",
"answer": "Yes",
"name": "Study"
}
]
},
{
"questions": [
{
"question": "Would you Love to learn about song?",
"answer": "Yes",
"name": "Song"
},
{
"question": "Would you Love to learn about rock?",
"answer": "No",
"name": "Song"
}
]
}
]
I have tried to map to two arrays ( from name and questions) and tried to combined them , but I can't make it work for multiple arrays in questions. How can I make this ? Is there any loadash way too accomplish this easily. But I'm trying to do this in Vanilla JavaScript way.
You can try with double .map():
let input = [
{
"name": "Study",
"questions": [
{
"question": "Would you Love to learn about Java?",
"answer": "Yes"
}
]
},
{
"name": "Song",
"questions": [
{
"question": "Would you Love to learn about song?",
"answer": "Yes"
},
{
"question": "Would you Love to learn about rock?",
"answer": "No"
}
]
}
]
let result = input.map(({name, questions}) => ({ questions: questions.map(q => ({name, ...q })) }));
console.log(result);
Try following
let arr1 = [
{
"name": "Study",
"questions": [
{
"question": "Would you Love to learn about Java?",
"answer": "Yes"
}
]
},
{
"name": "Song",
"questions": [
{
"question": "Would you Love to learn about song?",
"answer": "Yes"
},
{
"question": "Would you Love to learn about rock?",
"answer": "No"
}
]
}
]
arr1.map((element, index) => {
console.log(element); console.log(index); return
{
questions: element.questions.map((e, i) => {
console.log(e); console.log(i); return {
...e,
name: element.name
};
})
}
})
Related
I'm making a kanban task management app and I'm trying to remove a task with the _id: req.params.id which has the value of 62fa5ae05778ec97bc6ee23a. I tried the following:
const task = await Board.findOneAndUpdate(
{
"columns.tasks._id": req.params.id,
},
{ $pull: { "columns.$.tasks.$._id": req.params.id } },
{ new: true }
);
But I get the error Too many positional (i.e. '$') elements found in path'columns.$.tasks.$._id'
I searched for a while and came across arrayFilters from the docs but I'm struggling a lot to understand how to implement it for this particular need.
{
"_id": "62fa5aa25778ec97bc6ee231",
"user": "62f0eb5ebebd0f236abcaf9d",
"name": "Marketing Plan",
"columns": [
{
"name": "todo",
"_id": "62fa5aa25778ec97bc6ee233",
"tasks": [
{
"title": "Task Four",
"description": "This is task four",
"subtasks": [
{
"name": "wash dshes",
"completed": false,
"_id": "62fa5ae05778ec97bc6ee23b"
},
{
"name": "do homework",
"completed": false,
"_id": "62fa5ae05778ec97bc6ee23c"
}
],
"_id": "62fa5ae05778ec97bc6ee23a"
}
]
},
{
"name": "doing",
"_id": "62fa5aa25778ec97bc6ee234",
"tasks": []
},
{
"name": "done",
"_id": "62fa5aa25778ec97bc6ee235",
"tasks": []
}
],
"__v": 0
}
You need to use $[] positional operator in order to pull from the nested array. Try running this query:
db.Board.updateOne({
"_id" : "62fa5aa25778ec97bc6ee231",
}, {
$pull: { 'columns.$[].tasks': { '_id': '62fa5ae05778ec97bc6ee23a' } }
});
Hello I have JSON structured like this,
and I need to iterate over the items
[
{
"name": "About You",
"questions": [
{
"questionText": "What is your surname?",
"answers": [
{
"text": "Thomas"
}
]
},
{
"questionText": "Where do you work?",
"answers": [
{
"text": "Finance"
}
]
},
]
},
{
"name": "About Family",
"questions": [
{
"questionText": "Childeren",
"answers": [
{
"text": "Yes"
}
]
},
{
"questionText": "Married",
"answers": [
{
"text": "No"
}
]
},
]
},
{
"name": "Travel",
"questions": [
{
"questionText": "Do you travel a lot?",
"answers": [
{
"text": "Yes"
}
]
}
]
}
]
I started with this code but I don't know how to show all the nested items. Should I use another map function? I would like to have format that will show table with questionTexts and answers text
{details.map((detail, i) => (
<div key={i}>
<div>{detail.name}</div>
<div>{detail.questions ? detail.questions[0].questionText : ''}</div>
<div>{detail.questions ? detail.questions[0].answers[0].text : ''}</div>
</div>
)
)}
thank you
Should I use another map function?
Yes
First, map through the details array
details.map((detail, i) =>
Map through the current detail.questions
detail.questions.map((question) => (
Optionally, apply the same logic for question.answers
question.answers.map((question) => (
Small example were we show all the questions:
class Example extends React.Component {
render() {
const details = [{"name": "About You", "questions": [{"questionText": "What is your surname?", "answers": [{"text": "Thomas"} ] }, {"questionText": "Where do you work?", "answers": [{"text": "Finance"} ] }, ] }, {"name": "About Family", "questions": [{"questionText": "Childeren", "answers": [{"text": "Yes"} ] }, {"questionText": "Married", "answers": [{"text": "No"} ] }, ] }, {"name": "Travel", "questions": [{"questionText": "Do you travel a lot?", "answers": [{"text": "Yes"} ] } ] } ];
return (
details.map((detail, i) => (
<div key={detail.name} class='question'>
<b>{detail.name}</b>
{
detail.questions.map((question) => (
<em key={question.questionText}>
Question: {question.questionText}
</em>
))
}
</div>
))
);
}
}
ReactDOM.render(<Example />, document.body);
.question {
display: flex;
flex-direction: column;
margin-bottom: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Additional notes
Changed the key={} to the name of the question to we're sure it's unique
Added a key to the nested map(), using the question itself
Thx to #pilchard for noticing
I have this json:
[
{
"question": "1.1",
"level": 1,
"id": 4,
"answers": [
{
"text_answer": "NO",
"questions": [
{
"question": "1.1.1",
"level": 2,
"id": 3,
"answers": []
}
]
},
{
"text_answer": null,
"questions": [
{
"question": "1.1.2",
"level": 2,
"id": 2,
"answers": [
{
"text_answer": "SI",
"questions": [
{
"question": "1.1.2.1",
"level": 3,
"id": 1,
"answers": []
}
]
}
]
}
]
}
]
}
]
this json is dynamic and can have n amount of levels under the fields answers and questions that is why it is necessary to go through them with a recursive function
I want to get this output:
[
{
"question": "1.1",
"level": 1,
"id": 4,
"children": [
{
"question": "1.1.1",
"text_answer": "NO",
"level": 2,
"id": 3,
"children": []
},
{
"question": "1.1.2",
"text_answer": null,
"level": 2,
"id": 2,
"children": [
{
"question": "1.1.2.1",
"text_answer": "SI",
"level": 3,
"id": 1,
"children": []
}
]
}
]
}
]
the fields answers and questions no longer exist, they are renamed children and the content of both is unified.
I think this recursive function should do a double foreach, but I don't know how to do it.
function format(d) {
if (d.respuestas) {
d.respuestas.forEach((d) => {
format;
});
}
}
format(data);
var data= [
{
"question": "1.1",
"level": 1,
"id": 4,
"answers": [
{
"text_answer": "NO",
"questions": [
{
"question": "1.1.1",
"level": 2,
"id": 3,
"answers": []
}
]
},
{
"text_answer": null,
"questions": [
{
"question": "1.1.2",
"level": 2,
"id": 2,
"answers": [
{
"text_answer": "SI",
"questions": [
{
"question": "1.1.2.1",
"level": 3,
"id": 1,
"answers": []
}
]
}
]
}
]
}
]
}
]
/* [
{
"question": "1.1",
"level": 1,
"id": 4,
"children": [
{
"question": "1.1.1",
"text_answer": "NO",
"level": 2,
"id": 3,
"children": []
},
{
"question": "1.1.2",
"text_answer": null,
"level": 2,
"id": 2,
"children": [
{
"question": "1.1.2.1",
"text_answer": "SI",
"level": 3,
"id": 1,
"children": []
}
]
}
]
}
]
*/
function format(d) {
if (d.answers) {
d.answers.forEach((d) => {
format;
});
}
}
format(data);
**note:**
I changed the previous structure that I put to the question to make myself understand better.
Here is one approach via recurssion. I've commented the code to explain what exactly is going on line by line.
function _process(item) {
let result = item // we define a copy of item -> result
// this is renaming the field 'answers' (if found)
if (item.answers) {
result.children = item.answers.map(_process) // process each item separately
delete result.answers
}
// if there is a question field, extract the first item in the array and merge the attributes with result
if (item.questions) {
result = {
...result,
..._process(item.questions[0]) // also try to process the item before merging it (to check if there are nested 'questions' or 'answers' fields)
}
delete result.questions // remove the questions field
}
return result
}
function process(data) {
return data.map(_process) // start the recurssion for top-level objects
}
// sample data to test out
const data = [{
"question": "1.1",
"level": 1,
"id": 4,
"answers": [{
"text_answer": "NO",
"questions": [{
"question": "1.1.1",
"level": 2,
"id": 3,
"answers": []
}]
},
{
"text_answer": null,
"questions": [{
"question": "1.1.2",
"level": 2,
"id": 2,
"answers": [{
"text_answer": "SI",
"questions": [{
"question": "1.1.2.1",
"level": 3,
"id": 1,
"answers": []
}]
}]
}]
}
]
}]
const result = process(data)
console.log(JSON.stringify(result, null, 2))
You're on the right track in writing a recursive function.
Where I think you're going wrong is in thinking about 'pushing' it to an array or object to store the data.
Instead, what should happen is that your recursive function returns the formatted data, and then that data is added to new json object which is sent back up the call stack.
var data = {
"name": "1.question",
"answer": "YES",
"children": [{
"name": "1.1 question",
"answer": "yes"
},
{
"name": "1.2 question",
"answer": "NO",
"children": [{
"name": "1.2.1 question",
"answer": "NO"
}]
},
{
"name": "1.3 question",
"answer": "YES",
"children": [{
"name": "1.3.1 question",
"answer": "yes",
"children": [{
"name": "1.3.1.1 question",
"answer": "YES"
}]
}]
}
]
}
function format(d) {
if (d.children) {
// if there are children you are going to recurse deeper
// use the Array.prototype.map function to _transform_ each of the children.
const formattedChildren = d.children.map(v => {
return format(v);
});
// Notice that I'm returning a new object here, as well as
// An aggregation of the already transformed data
return {
data: "new formatted parent node data goes here",
children: formattedChildren
};
} else { // _always_ have a check for 'is it a leaf node'.
// If it's a leaf node node, just format it.
//Notice that I'm returning a new object here
return {
data: "new formatted leaf node data goes here"
};
}
}
console.log(format(data));
I don't know what you are trying to achieve, so I've left this blank. But this is the template for how you would recursively traverse and transform a nested object like this.
(Note that you don't need to have a data key, I've just put that in as a place holder. It looks like you want name and answered keys.
It works for me:
// here is your JSON
var json = [{
"question": "1.1",
"level": 1,
"id": 4,
"answers": [{
"text_answer": "NO",
"questions": [{
"question": "1.1.1",
"level": 2,
"id": 3,
"answers": []
}]
},
{
"text_answer": null,
"questions": [{
"question": "1.1.2",
"level": 2,
"id": 2,
"answers": [{
"text_answer": "SI",
"questions": [{
"question": "1.1.2.1",
"level": 3,
"id": 1,
"answers": []
}]
}]
}]
}
]
}]
// main
function change(branch) {
// the first level has a bit different structure
try {
if (branch.level == 1) {
return {
question: branch.question,
level: branch.level,
id: branch.id,
children: change(branch.answers)
}
}
} catch (e) {}
// next levels
var new_branch = [];
for (var i = 0; i < branch.length; i++) {
new_branch.push({
question: branch[i].questions[0].question,
text_answer: branch[i].text_answer,
level: branch[i].questions[0].level,
id: branch[i].questions[0].id,
children: [change(branch[i].questions[0].answers)].flat(1)
});
}
return new_branch;
}
// output
console.log(JSON.stringify(change(json[0])));
Hi I am trying to build a question and answer based on conditional flows.
Let's take my question in UI is below JSON:
{
"text": "What is the best cookie?",
"type": "mc",
"answers": [
"Chocolate Chip",
"Sugar",
"Beer"
],
"answer": "Sugar"
}
Let's take if the user selects Sugar and Beer as an option, I have put up a question from below JSON which maps to the selected answer if he chooses Beer then a different question from the JSON object.
If the user answers A and B for the first question, then the next question should be 3rd object in JSON, if C then 2nd Object from JSON, if C and A then the first Object from JSON.
Below is entire mock JSON I have
{
"title": "Quiz about Foo",
"questions": [
{
"text": "Is true true?",
"type": "tf",
"answer": "t"
},
{
"text": "Is false true?",
"type": "tf",
"answer": "f"
},
{
"text": "What is the best beer?",
"type": "mc",
"answers": [
"Coors",
"Miller",
"Bud",
"Anchor Steam"
],
"answer": "Anchor Steam"
},
{
"text": "What is the best cookie?",
"type": "mc",
"answers": [
"Chocolate Chip",
"Sugar",
"Beer"
],
"answer": "Sugar"
}
]
}
I'm not sure I fully understand your question. If you want each answer to point to the next question in your JSON, you have to add some kind of a question ID. You also need to convert your answers from strings to objects, so you can add the ID of the next question to them.
Something like:
{
"questions": [
{
"id": 1,
"text": "What is the best cookie?",
"type": "mc",
"answers": [
{ "text": "Chocolate Chip", "nextQuestionId": 2 },
{ "text": "Sugar", "nextQuestionId": 2 },
{ "text": "Beer", "nextQuestionId": 3 }
],
"answer": "Sugar"
},
{
"id": 2,
"text": "Second question?",
...
},
{
"id": 3,
"text": "Third question?",
...
}
]
}
This way you can write a simple generic logic that just follows the flow defined by the JSON.
I am trying to merge json format (prefably using underscore) but not sure how it could be done. The first json has no indicator of _id to be mapped.
JSON 1:
{
"0001": {
"answer": "sad"
},
"0002": {
"answer": "sad1"
}
}
JSON 2:
[
{
"_id": "0001",
"question": "who am I"
},
{
"_id": "0002",
"question": "How old are you?"
}
]
Final Result after merging:
[
{
"_id": "0001",
"question": "who am I",
"answer": "sad"
},
{
"_id": "0002",
"question": "How old are you?",
"answer": "sad1"
}
]
For the approach, i am trying to transform JSON 1 to following format first but unable to achieve.
[
{
"_id": "0001",
"answer": "sad"
},
{
"_id": "0002",
"answer": "sad1"
}
]
Ok, so you can do a foreach to add the new answer element:
var json1 = {
"0001": {
"answer": "sad"
},
"0002": {
"answer": "sad1"
}
};
var json2 = [
{
"_id": "0001",
"question": "who am I"
},
{
"_id": "0002",
"question": "How old are you?"
}
];
json2.forEach(function(o) {
o.answer = json1[o._id].answer;
});
console.log(json2);
I hope that helps :D