I'm looking to create a nested array based on reading a flat array. An example of the flat array I am reading is this:
const flatItems = [
{
"code": "CODE1",
"title": "Title 1",
"question": "Question 1",
"order": 0,
},
{
"code": "CODE2",
"title": "Title 2",
"question": "Question 2",
"order": 1,
},
{
"code": "CODE3",
"title": "Title 3",
"question": "Question 3",
"order": 2,
},
{
"code": "CODE4",
"title": "Title 4",
"question": "Question 4",
"order": 3,
},
];
And ideally I would like to place this into groups of 'Yes's and 'No's. The flat array is already in the correct order. There will only ever be one item in the 'Yes's but can have many in the 'No's depending on any conditions.
const treeItems = {
question: "Question 1",
options: [
{
value: "Yes",
items: [
{
code: "CODE1",
title: "Title 1"
}
]
},
{
value: "No",
question: "Question 2"
options: [
{
value: "Yes",
items: [
{
code: "CODE2",
title: "Title 2"
}
]
},
{
value: "No",
items: [
{
code: "CODE3",
title: "Title 3"
},
{
code: "CODE4",
title: "Title 4"
}
]
}
]
}
]
};
I am aware that reduce may be the best approach here, but would anyone have any good examples or recommended practices as how I should go about doing this?
If you want to group these items use "Yes" and "No" as the properties of the final object.
Using Array.reduce() sounds solid in this case.
Not sure how you want to group because your JSON is inconsistent.
const flatItems = [
{
"code": "CODE1",
"title": "Title 1",
"question": "Question 1",
"order": 0,
},
{
"code": "CODE2",
"title": "Title 2",
"question": "Question 2",
"order": 1,
},
{
"code": "CODE3",
"title": "Title 3",
"question": "Question 3",
"order": 2,
},
{
"code": "CODE4",
"title": "Title 4",
"question": "Question 4",
"order": 3,
},
];
const groupedObject = flatItems.reduce((tmpGroupedObject, item) => {
const groupingProperty = item.order < 2 ? "Yes" : "No"; /// grouping decision
if (!Array.isArray(tmpGroupedObject[groupingProperty])) {
tmpGroupedObject[groupingProperty] = []; /// make Obj["Yes"] an array
}
tmpGroupedObject[groupingProperty].push(item);
return tmpGroupedObject;
}, {});
console.log(groupedObject);
As mentioned in the comments, I'm confused by the requested output. I especially don't understand why CODE3 and CODE4 are on the same level, and not nested as another Yes/No pair. But we can write a fairly simple recursion to do that:
const convert = ([{code, title, question} = {}, ...items]) => ({
question,
options: [
{value: "Yes", items: [{code, title}]},
{value: "No", ... (items .length < 3 ? {items: items .map (({code, title}) => ({code, title}))} : convert (items))}
]
})
const flatItems = [{code: "CODE1", title: "Title 1", question: "Question 1", order: 0}, {code: "CODE2", title: "Title 2", question: "Question 2", order: 1}, {code: "CODE3", title: "Title 3", question: "Question 3", order: 2}, {code: "CODE4", title: "Title 4", question: "Question 4", order: 3}]
console .log (
convert (flatItems)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
However by changing < 3 to < 2, we get what I think of as a much more logical grouping:
const convert = ([{code, title, question} = {}, ...items]) => ({
question,
options: [
{value: "Yes", items: [{code, title}]},
{value: "No", ... (items .length < 2 ? {items: items .map (({code, title}) => ({code, title}))} : convert (items))}
]
})
const flatItems = [{code: "CODE1", title: "Title 1", question: "Question 1", order: 0}, {code: "CODE2", title: "Title 2", question: "Question 2", order: 1}, {code: "CODE3", title: "Title 3", question: "Question 3", order: 2}, {code: "CODE4", title: "Title 4", question: "Question 4", order: 3}]
console .log (
convert (flatItems)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
I hope one of these does what you want.
Also, again, welcome to StackOverflow. Next time, please be sure to post your own attempted solution in the question. Even if it's not working properly, we can often either help you fix it, or explain why it's headed down the wrong path altogether.
Related
Hey guys I have the following array that's used to display a flatlist within my app.
Array [
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
},
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "1,16,19",
},
]
However I would like to sort this array based off the subjects value. In the app the user can select a couple of subjects which are represented by numbers so lets say the users selected subjects are:
11, 4, 2, 1
I would like to sort the array so that the items with 3 or more subjects in common with the user are sorted to the top and then items with two and then 1 and then none so the array above should look like this after sorting:
Array [
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
},
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "0,16,19",
},
]
How can I achieve this?
I have been searching around the array sort function:
Array.prototype.sort()
However I have only seen how to sort based off number comparisons I have never seen an array sorted based off values in common. Please could someone help me with this!
EDIT
Array [
Object {
"data": "Item 2",
"id": "2",
"subjects": "8,11,2,4,16,19",
"ranking": "green",
},
Object {
"data": "Item 1",
"id": "1",
"subjects": "1,8,9,23,11,15,16,14,20",
"ranking": "amber",
},
Object {
"data": "Item 3",
"id": "3",
"subjects": "16,20,14,11,9,2",
"ranking": "amber",
},
Object {
"data": "Item 4",
"id": "4",
"subjects": "0,16,19",
"ranking": "red",
},
]
You could create an object with counts of selected subjects and sort descending by this value.
const
data = [{ data: "Item 1", id: "1", subjects: "1,8,9,23,11,15,16,14,20" }, { data: "Item 2", id: "2", subjects: "8,11,2,4,16,19" }, { data: "Item 3", id: "3", subjects: "16,20,14,11,9,2" }, { data: "Item 4", id: "4", subjects: "1,16,19" }],
selected = [11, 4, 2, 1],
counts = data.reduce((r, { id, subjects }) => {
r[id] = subjects
.split(',')
.reduce((s, v) => s + selected.includes(+v), 0);
return r;
}, {});
data.sort((a, b) => counts[b.id] - counts[a.id]);
console.log(data);
console.log(counts);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I don't understand because I use the method "find" but I get "undefined"...
My data :
[
{ "id": 2, "title": "My project", "nameStructure": "Entreprise", "studies":
[
{"id": 3, "name": "My stidue", "status": "in prepa" },
{ "id": 4, "name": "My second study ", "status": "In"}
],
"typeStructure": "Entreprise"
},
{ "id": 3, "title": "My project 2", "nameStructure": "Entreprise 2", "studies":
[
{"id": 4, "name": "My stidue 2", "status": "in prepa" },
{ "id": 5, "name": "My second study 2 ", "status": "In"}
],
"typeStructure": "Entreprise 2"
},
...
]
I would like to have only the object with the ID 2 for example.
So I wrote :
const id = 2
myarray.filter(p => p.id === id);
But it does not work... I always get "undefined"
Thanks for help
ID is a number, therefore you need to remove the quotes around 2
myarray.filter(p => p.id === 2);
and the operator === in Javascript means that 2 should be equal to "2" as in value and type
reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality
const arr = [
{
id: 2,
title: "My project",
nameStructure: "Entreprise",
studies: [
{ id: 3, name: "My stidue", status: "in prepa" },
{ id: 4, name: "My second study ", status: "In" }
],
typeStructure: "Entreprise"
},
{
id: 3,
title: "My project 2",
nameStructure: "Entreprise 2",
studies: [
{ id: 4, name: "My stidue 2", status: "in prepa" },
{ id: 5, name: "My second study 2 ", status: "In" }
],
typeStructure: "Entreprise 2"
}
];
const newItem = arr.find((item) => item.id === 2);
console.log("newItem>>>>", newItem);
how can I assign object property value as property key?
I have a set of data:
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
]
I want to reformat it to become:
const mydata = [
{
"Title 1": "Value 1"
},
{
"Title 2": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
]
},
]
I have tried this code to achieve it:
mydata.map((dt: any) => {
dt.title: dt.value
});
However, it seems not working.
Any idea how can I reformat it to the one I desire?
Thanks.
Please use following code.
Reference URL How to use a variable for a key in a JavaScript object literal?
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
];
let reData = [];
mydata.forEach((dt)=>{
reData.push({[dt.title]: dt.value});
});
console.log(reData);
If you want to transform the array to a different type of variable, use [reduce][1]
const mydata = [
{
id: 001,
value: "Value 1",
title: "Title 1",
},
{
id: 002,
value: [
{
Name: "Name 1",
Age: "20",
},
{
Name: "Name 2",
Age: "30",
},
],
title: "Title 2",
},
];
const data = mydata.reduce(
(acc, cur) => ({ ...acc, [cur.title]: cur.value }),
{}
);
console.log(data);
Your map function has an error, and your key assignment has another one. Let's fix it.
const newData = mydata.map((dt: any) => ({
[dt.title]: dt.value,
}));
First: You can't return an object from an arrow function without parenthesis, if you don't use it, the code will think it is a function body not an object.
Second: If you want to return a value as a key, you need put it inside "[ ]" (Square brackets)
Just that, simple mistakes, at the end you came up with the right logic to solve it
Add brackets around the return value.
Use square brackets for a computed property name.
const mydata = [
{
"id": 001,
"value": "Value 1",
"title": "Title 1"
},
{
"id": 002,
"value": [
{
"Name": "Name 1",
"Age": "20"
},
{
"Name": "Name 2",
"Age": "30"
},
],
"title": "Title 2"
},
];
const res = mydata.map(({value, title})=>({[title]: value}));
console.log(res);
I have two almost identical arrays of objects, the only difference between them is that the first array consists of inner arrays with objects having a text1 attribute, and the second array has text2 property instead. Each array contains 800 objects with same keys 1, 2, 3, 4 ....
How can I merge these two arrays? I tried with push function but got only the first array. Is there some other way to merge two arrays like reduce, filter or some other function?
let arr1 = [{
"1": [{
"text1": "Some text 1",
"englishName": "Name 1",
"number": 1,
},
{
"text1": "Some text 2",
"englishName": "Name 2",
"number": 2,
}
]
},
{
"2": [{
"text1": "Some text 3",
"englishName": "Name 3",
"number": 3,
},
{
"text1": "Some text 4",
"englishName": "Name 4",
"number": 4,
}
]
}
]
let arr2 = [{
"1": [{
"text2": "Some new text",
"englishName": "Name 1",
"number": 1
},
{
"text2": "Some new text 2",
"englishName": "Name 2",
"number": 2,
}
]
},
{
"2": [{
"text2": "Some new text 3",
"englishName": "Name 3",
"number": 3,
},
{
"text2": "Some new text 4",
"englishName": "Name 4",
"number": 4,
}
]
}
]
i need to merge in one array and concat text2 to first array like this
let mergearray = [
{
"1": [
{
"text1": "Some text 1",
"text2": "Some new text 1",
"englishName": "Name 1",
"number": 1,
},
{
"text1": "Some text 2",
"text2": "Some new text 2",
"englishName": "Name 2",
"number": 2,
}
]
},
{
"2": [
{
"text1": "Some text 3",
"text2": "Some new text 3",
"englishName": "Name 3",
"number": 3,
},
{
"text1": "Some text 4",
"text2": "Some new text 4",
"englishName": "Name 4",
"number": 4,
} ] } ]
How compare keys of arrays?
you can use JavaScript Array concat() method
the concat() method is used to join two or more arrays.
This method does not change the existing arrays, it returns a new array, containing the values of the joined arrays. you can do that like this
let arr= arr1.concat(arr2);
console.log(JSON.stringify(arr));
it will give you this result
[{"1":[{"text1":"Some text 1","englishName":"Name 1","number":1},{"text1":"Some text 2","englishName":"Name 2","number":2}]},
{"2":[{"text1":"Some text 3","englishName":"Name 3","number":3},{"text1":"Some text 4","englishName":"Name 4","number":4}]},
{"1":[{"text2":"Some new text","englishName":"Name 1","number":1},{"text2":"Some new text 2","englishName":"Name 2","number":2}]},
{"2":[{"text2":"Some new text 3","englishName":"Name 3","number":3},{"text2":"Some new text 4","englishName":"Name 4","number":4}]}]
Try this:
const arr3 = arr1.reduce((acc, item, index, array) => {
if (arr2.length > index) {
array[index][index + 1][0].text2 = arr2[index][index + 1][0].text2;
acc = array.map((item, index2) => {
return item[index2 + 1][0];
});
}
return acc;
}, []);
console.log(JSON.stringify(arr3.reverse()))
I'm building a small application in VueJS where I'm getting a response in following format:
"meeting_summaries":[
{
"interaction_id":22,
"nature":"1",
"client_name":"Test Company 4",
},
{
"interaction_id":22,
"nature":"2",
"client_name":"Test Company 5",
}
]
And I'm having a data set of nature as:
const nature = [
{value: 1, label: "Demo 1"},
{value: 2, label: "Demo 2"},
{value: 3, label: "Demo 3"}
]
I want to map my meeting_summaries with this data set were in meeting_summaries -> nature points to nature -> value so that my final output can look something like this:
"meeting_summaries":[
{
"interaction_id":22,
"nature":"1",
'nature_name": "Demo 1",
"client_name":"Test Company 4",
},
{
"interaction_id":22,
"nature":"2",
'nature_name": "Demo 2",
"client_name":"Test Company 5",
}
]
You could use a hash table and then iterate the meeting_summaries.
const object = { meeting_summaries: [{ interaction_id: 22, nature: "1", client_name: "Test Company 4" }, { interaction_id: 22, nature: "2", client_name: "Test Company 5", mention_name: "Analyst" }] },
nature = [{ value: 1, label: "Demo 1" }, { value: 2, label: "Demo 2" }, { value: 3, label: "Demo 3" }],
natureMap = Object.assign(...nature.map(o => ({ [o.value]: o.label })));
object.meeting_summaries.forEach(o => o.nature_name = natureMap[o.nature]);
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Just map through array an add your property using Object.assing and Array.prototype.find:
const a = {
"meeting_summaries":[
{
"id":1,
"company_id":7,
"interaction_id":22,
"nature":"1",
"user_id":1,
"action":"Action Test 1",
"feedback":"Comment Test 1",
"created_at":"2017-06-04 10:15:02",
"updated_at":"2017-06-04 10:15:02",
"deleted_at":null,
"client_name":"Test Company 4",
"mention_name":"Analyst"
},
{
"id":2,
"company_id":8,
"interaction_id":22,
"nature":"2",
"user_id":1,
"action":"Action Test 2",
"feedback":"Comment Test 2",
"created_at":"2017-06-04 10:15:02",
"updated_at":"2017-06-04 10:15:02",
"deleted_at":null,
"client_name":"Test Company 5","mention_name":"Analyst"
}
]
};
const nature = [
{value: 1, label: "Demo 1"},
{value: 2, label: "Demo 2"},
{value: 3, label: "Demo 3"},
{value: 4, label: "Demo 4"},
{value: 5, label: "Demo 5"}
]
const res = a.meeting_summaries.map(ms => Object.assign(ms,
(nature.find(n => n.value == ms.nature)) // if corresponding object exists
? { nature_name: nature.find(n => n.value == ms.nature).label } : {}
))
console.log(res)
You didn't provide full context, but let's assume that "meeting_summaries" is variable:
var meeting_summaries = [{
"interaction_id": 22,
"nature": "1",
"client_name": "Test Company 4",
},
{
"interaction_id": 22,
"nature": "2",
"client_name": "Test Company 5",
"mention_name": "Analyst"
}
]
const nature = [
{ value: 1, label: "Demo 1" },
{ value: 2, label: "Demo 2" },
{ value: 3, label: "Demo 3" }
]
var meeting_summaries = meeting_summaries.map(ms => {
ms.nature_name = nature.find(n => ms.nature == n.value).label;
return ms
})
console.log(meeting_summaries)
I'm just take a "map" approach in my solution for better performance:
const meeting_summaries = [ { "interaction_id":22, "nature":"1", "client_name":"Test Company 4", }, { "interaction_id":22, "nature":"2", "client_name":"Test Company 5", } ];
const nature = [ {value: 1, label: "Demo 1"}, {value: 2, label: "Demo 2"}, {value: 3, label: "Demo 3"} ];
const natureMap = nature.reduce((accum,current)=>{
accum[current.value] = current.label;
return accum;
}, { });
const result = meeting_summaries.map(item => {
item.nature_name = natureMap[item.nature];
return item;
});
console.log(result)
Sorry for indentation, coded from smartphone
const baseObj = {
"meeting_summaries": [
{
"interaction_id": 22,
"nature": "1",
"client_name": "Test Company 4",
},
{
"interaction_id": 22,
"nature": "2",
"client_name": "Test Company 5",
}
]
}
const natures = [
{value: 1, label: "Demo 1"},
{value: 2, label: "Demo 2"}
]
const meeting_summaries = baseObj.meeting_summaries
natures.forEach((nature, index) => {
meeting_summaries[index]["nature_name"] = nature.label
})
console.log(baseObj)
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do Array.prototype.forEach() and add the nature_name property of the found element label:
const nature = [{value: 1, label: "Demo 1"},{value: 2, label: "Demo 2"},{value: 3, label: "Demo 3"}];
const obj = {meeting_summaries: [{"interaction_id":22,"nature":"1","client_name":"Test Company 4",},{"interaction_id":22,"nature":"2","client_name":"Test Company 5"}]};
obj.meeting_summaries.forEach(el => el.nature_name = nature.find(n => n.value == el.nature).label);
console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: 0; }