Related
I want to concatenate the values of objects in different arrays to one side.
I tried to output the data value received in json to console.log.
I want to put the values in the Ingredient List into the List array.
console.log(detail);
{
List: [
{
id: 120,
content: "stack-overflow",
functionalList: [
{
id: 832,
},
],
},
{
id: 230,
content: "heap-overflow",
functionalList: [
{
id: 24,
},
],
},
],
ListValue: [
{
IngredientList: [
{
id: 1,
value: 43
},
{
id: 23,
value: 23
},
],
},
],
},
]);
I want to put ListValue -> IngredientList value values into List array object.
How can I do it this way? I've been trying all day, but it's hard for me.
{
List: [
{
id: 120,
content: "stack-overflow",
value: 43
functionalList: [
{
id: 832,
functionalId: 37
},
],
},
{
id: 230,
content: "heap-overflow",
value: 23
functionalList: [
{
id: 24,
functionalId: 12
},
],
},
],
ListValue: [
{
IngredientList: [
{
id: 1,
value: 43
},
{
id: 23,
value: 23
},
],
},
],
},
]);
This should work in a mutable approach, even if you have multiple objects inside ListValue:
data.List = [
...data.List,
...data.ListValue.reduce((arr, el) => {
arr.push(...el.IngredientList);
return arr;
}, []),
];
It's not clear which value of the IngredientList should go in which item of List. Supposing you always want to pair the first value with the first item, the second with the second, and so on...
const obj = {
List: [
{
id: 120,
content: "stack-overflow",
functionalList: [
{
id: 832,
},
],
},
{
id: 230,
content: "heap-overflow",
functionalList: [
{
id: 24,
},
],
},
],
ListValue: [
{
IngredientList: [
{
id: 1,
value: 43,
},
{
id: 23,
value: 23,
},
],
},
],
};
const ingridientsValue = obj.ListValue[0].IngredientList.map(el => el.value); // [43, 23]
for (const item of obj.List) item.value = ingridientsValue.shift();
console.log(obj.List);
I have solved this. Check it out here: https://jsfiddle.net/bowtiekreative/o5rhy7c1/1/
First your JSON needs to be validated.
Remove the ")" and the extra ","
Instructions
Create an empty array called arr.
Loop through the ListValue array.
For each item in the ListValue array, loop through the IngredientList array.
For each item in the IngredientList array, push the value property into the arr array.
Log the arr array to the console.
Example:
var json = {
"List":[
{
"id":120,
"content":"stack-overflow",
"functionalList":[
{
"id":832
}
]
},
{
"id":230,
"content":"heap-overflow",
"functionalList":[
{
"id":24
}
]
}
],
"ListValue":[
{
"IngredientList":[
{
"id":1,
"value":43
},
{
"id":23,
"value":23
}
]
}
]
};
var arr = [];
for (var i = 0; i < json.ListValue.length; i++) {
for (var j = 0; j < json.ListValue[i].IngredientList.length; j++) {
arr.push(json.ListValue[i].IngredientList[j].value);
}
}
console.log(arr)
I would like to update the object with values after a recursive search finds a particular node.
Where do I need to add logic to achieve this?
I would like to get the first found object from the nested array of objects and update the data with selected:true based on the iterations to get the value showTree: true.
Function:
let findDeep = function(data, label) {
return data.filter(function(e) {
if (e.label.includes(label)) {
data.map(el=> el.selected= "true"); // logic to select the first found value
return e;
}
else if (e.item)
//logic for showTree: true
return findDeep(e.item, label);
});
};
Data:
let testData = [
{
id: 1,
label: 'parent1',
item: [
{
id: 21,
label: 'child1',
item: [
{
id: 211,
label: 'child31',
item: [
{
id: 2111,
label: 'child2211',
item: [
{
id: 21111,
label: 'child22111'
}
]
}
]
},
{
id: 222,
label: 'child32'
}
]
},
{
id: 22,
label: 'child2',
item: [
{
id: 221,
label: 'child421',
item: [
{
id: 2211,
label: 'child2211'
}
]
},
{
id: 222,
label: 'child222'
}
]
}
]
},
{
id: 2,
label: 'parent2',
item: [
{
id: 21,
label: 'child2',
item: [
{
id: 511,
label: 'child51',
item: [
{
id: 5111,
label: 'child5211',
item: [
{
id: 51111,
label: 'child52111'
}
]
}
]
},
{
id: 522,
label: 'child352'
}
]
}
]
}
];
I would like to achieve something in the output
console.log(findDeep(testData, 'child3')[0]);
//output list
[
{
"id":1,
"label":"parent1",
"showTree": true,
"item":[
{
"id":21,
"label":"child1",
"showTree": true,
"item":[
{
"id":211,
"label":"child31",
"selected" true,
"item":[
{
"id":2111,
"label":"child2211",
"item":[
{
"id":21111,
"label":"child22111"
}
]
}
]
},
{
"id":222,
"label":"child32"
}
]
},
{
"id":22,
"label":"child2",
"item":[
{
"id":221,
"label":"child421",
"item":[
{
"id":2211,
"label":"child2211"
}
]
},
{
"id":222,
"label":"child222"
}
]
}
]
},
{
"id":2,
"label":"parent2",
"item":[
{
"id":21,
"label":"child2",
"item":[
{
"id":511,
"label":"child51",
"item":[
{
"id":5111,
"label":"child5211",
"item":[
{
"id":51111,
"label":"child52111"
}
]
}
]
},
{
"id":522,
"label":"child352"
}
]
}
]
}
]
//ouptput selected value
{
"id":211,
"label":"child31",
"selected":true,
"item":[
{
"id":2111,
"label":"child2211",
"item":[
{
"id":21111,
"label":"child22111"
}
]
}
]
}
You can do a normal tree search, modify the found property, then pass true back up the tree towards the root, applying showTree: true along the way.
Note that this is an in-place approach, so the semantics are a little different than you show on your call. That's probably most appropriate for an algorithm like this that is just modifying a few properties on an existing structure rather than reallocating the whole thing from scratch. It's an antipattern to return the original structure for in-place algorithms as .sort() and .reverse() do for the purposes of chaining -- this can lead to surprising and subtle bugs.
const expandPath = (nodes, targetLabel) => {
for (const node of nodes || []) {
if (node.label.includes(targetLabel)) {
return node.selected = true;
}
else if (expandPath(node.item, targetLabel)) {
return node.showTree = true;
}
}
};
const testData = [ { id: 1, label: 'parent1', item: [ { id: 21, label: 'child1', item: [ { id: 211, label: 'child31', item: [ { id: 2111, label: 'child2211', item: [ { id: 21111, label: 'child22111' } ] } ] }, { id: 222, label: 'child32' } ] }, { id: 22, label: 'child2', item: [ { id: 221, label: 'child421', item: [ { id: 2211, label: 'child2211' } ] }, { id: 222, label: 'child222' } ] } ] }, { id: 2, label: 'parent2', item: [ { id: 21, label: 'child2', item: [ { id: 511, label: 'child51', item: [ { id: 5111, label: 'child5211', item: [ { id: 51111, label: 'child52111' } ] } ] }, { id: 522, label: 'child352' } ] } ] } ];
expandPath(testData, "child3");
console.log(testData[0]);
Note that the added properties are at the bottom of each node.
Also, in your original attempt, please avoid using map for in-place operations -- its purpose is to allocate a new array, not modify it. Use forEach instead.
I would suggest to use string methods, like
- `includes` or
- `startsWith`
along with the wanted parameter.
search = (array, type, value) => array.some(o => {
if (o.label[type](value)) return o.selected = true;
return search(o.item || [], type, value);
})
Trying to figure out the best way to filter the nested object to get every category with an id of '2' or whatever. Want it so it only return those specific nodes.
const data = [
{
node: {
categories: [
{id: 2 }
]
}
},
{
node: {
categories: [
{id: 3}
]
}
},
{
node: {
categories: [
{id: 3}
]
}
},
{
node: {
categories: [
{ id: 5 }
]
}
},
{
node: {
categories: [
{ id: 2 }
]
}
},
]
Tried something like this but doesn't seem to work.
return data.filter(e => {
return e.node.categories.forEach(category => {
category.id == '2';
});
});
If you want to return any node which has a category id of 2, you can filter based on some of the id values being equal to 2:
const data = [
{
node: { categories: [ { id: 2 } ] }
},
{
node: { categories: [ { id: 3 } ] }
},
{
node: { categories: [ { id: 3 } ] }
},
{
node: { categories: [ { id: 5 } ] }
},
{
node: { categories: [ { id: 2 } ] }
},
]
const result = data.filter(e => e.node.categories.some(c => c.id == 2));
console.log(result);
we can use find to search if the category contain specific id or not.
const data = [
{
node: {
categories: [{ id: 2 }],
},
},
{
node: {
categories: [{ id: 3 }],
},
},
{
node: {
categories: [{ id: 3 }],
},
},
{
node: {
categories: [{ id: 5 }],
},
},
{
node: {
categories: [{ id: 2 }],
},
},
];
const result = data.filter(({ node }) => {
return node.categories.find((cat) => cat.id === 2);
});
console.log(result);
HI All I am having two array of object my aim is to compare them and filter out the matched result
my data looks like this
let data1 = [
{
name:'tom',
process:'flipkart',
master:'pharma',
profiles: [
{
level:'begginer',
language:'hindi',
role:['flp_admin','flp_teacher']
}
]
},
{
name:'jeo',
process:'amazon',
master:'science',
profiles: [
{
level:'begginer',
language:'english',
role:['amz_admin']
}
]
},
{
name:'jerry',
process:'email',
master:'it',
profiles: [
{
level:'begginer',
language:'urdu',
role:['eml_teacher']
}
]
}
]
let data2 = [
{
masterName:'Pharma',
businessProcess: [
{ label:'flipkart', value:'flipkart' },
{ label:'amazon', value:'amazon' }
]
},
{
masterName:'science',
businessProcess: [
{ label:'flipkart', value:'flipkart' },
{ label:'amazon', value:'amazon' }
]
},
{
masterName:'it',
businessProcess: [
{ label:'email', value:'email' },
{ label:'amazon', value:'amazon' }
]
}
I want to compare data1 with data2 and return the match from data2 if master of data1 matches with masterName of data2 and if business of data1 matches with businessProcess.label of data2.
Could anyone please tell me how can I do it?
You can use Array.filter and Array.find to loop over and find the matching items:
let data1 = [{
name: 'tom',
process: 'flipkart',
master: 'pharma',
profiles: [{
level: 'begginer',
language: 'hindi',
role: ['flp_admin', 'flp_teacher']
}]
},
{
name: 'jeo',
process: 'amazon',
master: 'science',
profiles: [{
level: 'begginer',
language: 'english',
role: ['amz_admin']
}]
},
{
name: 'jerry',
process: 'email',
master: 'it',
profiles: [{
level: 'begginer',
language: 'urdu',
role: ['eml_teacher']
}]
}
]
let data2 = [{
masterName: 'Pharma',
businessProcess: [{
label: 'flipkart',
value: 'flipkart'
},
{
label: 'amazon',
value: 'amazon'
}
]
},
{
masterName: 'science',
businessProcess: [{
label: 'flipkart',
value: 'flipkart'
},
{
label: 'amazon',
value: 'amazon'
}
]
},
{
masterName: 'it',
businessProcess: [{
label: 'email',
value: 'email'
},
{
label: 'amazon',
value: 'amazon'
}
]
}
];
console.log(data1.filter((d) => {
return data2.find((d2) => {
//check if data matername equals data1 master
// or if data1.process value exists in one of the item of businessProcess as value
return d2.masterName == d.master || d2.businessProcess.find(b => b.value === d.process);
});
}));
I am solving the problem as follows:
I have an array of objects with input format:
let allTasks = [
{
time: "07-2020",
tasks: [
{
code: "p1",
value: 1111
}
],
},
{
time: "07-2020",
tasks: [
{
code: "p2",
value: 2222
}
]
},
{
time: "08-2020",
tasks: [
{
code: "p1",
value: 3333
}
]
},
{
time: "08-2020",
tasks: [
{
code: "p2",
value: 4444
}
]
},
{
time: "09-2020",
tasks: [
{
code: "p1",
value: 5555
}
]
},
{
time: "09-2020",
tasks: [
{
code: "p2",
value: 6666
}
]
},
]
I want to convert into a format that is formatted as follows:
output = [
{
p1: [
["07-2020",1111],
["08-2020",3333],
["09-2020",5555],
]
},
{
p2: [
["07-2020",2222],
["08-2020", 4444],
["09-2020", 6666],
]
},
// ... p3, p4....
]
I use reduce() method to group the objects in an array.
let newArr = [];
allTasks.forEach((x,index)=>{
newArr.push({
tasks: x.tasks.map(y=>Object.assign(y,{time: x.time}))
})
})
console.log('newArr',newArr);
let listTask = newArr.flatMap(x=>x.tasks);
let groupData = listTask.reduce((gr,item)=>{
gr[item.code] = [...gr[item.code] || [],item];
return gr;
},[])
let newGroupData = Object.entries(groupData).map(([key,data])=>{
console.log('-------------------------')
let result = Object.values(data.reduce((arr,item)=>{
arr[item.time] = arr[item.time] || [item.time];
arr[item.time].push(item.value);
return arr;
},[]));
return {
[key]: result
}
})
console.log('newGroupData',newGroupData)
The results have been expected as above. But my code is long, how do I refactor my code and is there a better way to do it ?
Please help me.
Thank you!
A different approach
You could flatten the tasks first, with complemented key-value pair of time. To array of this
[
...
{ code: 'p1', value: 1111, time: '07-2020' }
...
]
After that, group task by code and do some manipulation with the grouped to achieve your expected result
const groupByCode = {}
allTasks
.flatMap((parentTask) =>
parentTask.tasks.map((task) => ({ ...task, time: parentTask.time }))
)
.forEach((flattenedTask) => {
if (groupByCode[flattenedTask.code]) {
groupByCode[flattenedTask.code].push(flattenedTask)
} else {
groupByCode[flattenedTask.code] = [flattenedTask]
}
})
const res = Object.entries(groupByCode).map(([code, tasks]) => ({
[code]: tasks.map((task) => [task.time, task.value]),
}))
Full implementation
let allTasks = [
{
time: "07-2020",
tasks: [
{
code: "p1",
value: 1111,
},
],
},
{
time: "07-2020",
tasks: [
{
code: "p2",
value: 2222,
},
],
},
{
time: "08-2020",
tasks: [
{
code: "p1",
value: 3333,
},
],
},
{
time: "08-2020",
tasks: [
{
code: "p2",
value: 4444,
},
],
},
{
time: "09-2020",
tasks: [
{
code: "p1",
value: 5555,
},
],
},
{
time: "09-2020",
tasks: [
{
code: "p2",
value: 6666,
},
],
},
]
const groupByCode = {}
allTasks
.flatMap((parentTask) =>
parentTask.tasks.map((task) => ({ ...task, time: parentTask.time }))
)
.forEach((flattenedTask) => {
if (groupByCode[flattenedTask.code]) {
groupByCode[flattenedTask.code].push(flattenedTask)
} else {
groupByCode[flattenedTask.code] = [flattenedTask]
}
})
const res = Object.entries(groupByCode).map(([code, tasks]) => ({
[code]: tasks.map((task) => [task.time, task.value]),
}))
console.log(JSON.stringify(res, null, 2))
Reference
Array.prototype.flatMap()
Object.entries()