I want to combine the values ​of objects in different arrays by sorting them one side - javascript

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)

Related

Merge nested Array with same key javascript

I have to organise the array, Getting a response array like this
let data = [
{
date: "2022-07-01T07:26:22",
tips: [
{ id: 1 }
]
},
{
date: "2022-07-01T12:05:55",
tips: [
{ id: 1 }
]
},
{
date: "2022-07-05T13:09:16",
tips: [
{ id: 1 }
]
},
{
date: "2022-07-05T13:31:07",
tips: [
{ id: 1 }
]
},
{
date: "2022-06-29T09:21:26",
tips: [
{ id: 1 }
]
}
]
The desired output :
let data = [
{
'2022-07-01': [
{
tips: [
{ id: 1 }
]
},
{
tips: [
{ id: 1 }
]
},
]
},
{
'2022-07-05': [
{
tips: [
{ id: 1 }
]
},
{
tips: [
{ id: 1 }
]
},
]
},
{
'2022-06-29': [
{
tips: [
{ id: 1 }
]
},
]
}
]
I need to get data with the same key in the above array format. I have tried different ways to achieve this but have not gotten the proper result Which is the best way to get the desired output.
Thanks in advance!!!
Here is a solution using reduce. Grouping first using reduce and after that getting the values of the object using Object.values
let data = [ { date: "2022-07-01T07:26:22", tips: [ { id: 1 } ] }, { date: "2022-07-01T12:05:55", tips: [ { id: 1 } ] }, { date: "2022-07-05T13:09:16", tips: [ { id: 1 } ] }, { date: "2022-07-05T13:31:07", tips: [ { id: 1 } ] }, { date: "2022-06-29T09:21:26", tips: [ { id: 1 } ] }]
let res = Object.values(data.reduce((acc,{date,tips})=>{
let key = date.substring(0,10)
acc[key] = acc[key] || {[key]:[]}
acc[key][key].push({tips})
return acc
},{}))
console.log(res)
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to filter array key by another array number key

I have 2 array, first array structure is:
items: [
{
name: "a",
items: [
{ name: "jack" },
{ name: "jose" },
]
},
{
name: "b",
items: [
{ name: "lara" },
{ name: "jo" },
]
},
{
name: "c",
items: [
{ name: "andy" },
{ name: "hary" },
]
}
]
and the second array:
number: [
0: [0, 1],
1: [1],
2: [0]
]
How to filter "items" by "number" and How can such an output be obtained? (the best solution)
{["jack", "jole"],["jo"],["andy"]}
A few maps would do it:
the output you wish is not valid JS so I made a nested array
const arr1 = [{ name: "a", items: [{ name: "jack" }, { name: "jose" }, ] }, { name: "b", items: [{ name: "lara" }, { name: "jo" }, ] }, { name: "c", items: [{ name: "andy" }, { name: "hary" }, ] } ], numbers = [ [0, 1], [1], [0] ];
const res = numbers
.map((arr, i) => arr
.map(key => arr1[i].items[key].name)
)
console.log(res)
If your number variable has to be an Object.
let items = [
{
name: "a",
items: [{ name: "jack" }, { name: "jose" }]
},
{
name: "b",
items: [{ name: "lara" }, { name: "jo" }]
},
{
name: "c",
items: [{ name: "andy" }, { name: "hary" }]
}
];
let number = {
0: [0, 1],
1: [1],
2: [0]
};
let result = []
for (const [key, value] of Object.entries(number)){
let names = []
value.forEach(value => {
names.push(items[key].items[value].name)
})
result.push(names)
}
console.log(result)

how to update array of objects if it matches while recursively search in JavaScript

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

A field from nested object to array [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have the following object, and I want to put all the ids in one array.
let obj = {
_id: 1,
children: [
{
id: 2,
children: [
{
id: 21,
children: [],
},
{
id: 22,
children: [],
},
{
id: 23,
children: [
{
id: 231,
children: [],
}
]
}
]
},
{
id: 3,
children: [
{
id: 31,
children: [],
},
{
id: 32,
children: [],
isCriteria: true
},
{
id: 33,
isCriteria: true
}
]
}
]
}
I want in result:
[1, 2, 21, 22, 23, 231, 3, 31, 32, 33]
PS: the object is set dynamically, so we don't know how deep the children are.
This one is uglier, but also should be lighter on garbage collector because it does not create and spread temporary arrays.
/**
* #param {number[]} arr Target array to which numbers will be appended
* #param {object} obj Source data
* #return {number[]} arr mutated with additional numbers (if any found)
*/
function arrayAppendIdsFrom (arr, obj) {
arr.push(obj.id);
if (Array.isArray(obj.children) && obj.children.length > 0) {
obj.children.forEach(child => arrayAppendIdsFrom(arr, child));
}
return arr;
}
/*
* Example data
*/
let obj = {
id: 1,
children: [
{
id: 2,
children: [
{
id: 21,
children: [],
},
{
id: 22,
children: [],
},
{
id: 23,
children: [
{
id: 231,
children: [],
}
]
}
]
},
{
id: 3,
children: [
{
id: 31,
children: [],
},
{
id: 32,
children: [],
isCriteria: true
},
{
id: 33,
isCriteria: true
}
]
}
]
};
// Example use
console.log(arrayAppendIdsFrom([], obj));
You'll need a recursive iteration. Quick example:
let ids = [];
function getIds(obj) {
// check for id
if (obj.hasOwnProperty('id')) {
ids = [...ids, obj.id];
}
// check for children and do recursive check
if (obj.hasOwnProperty('children') && obj.children.length > 0) {
obj.children.forEach(child => {
getIds(child);
});
}
}
// obj here is your exmple obj with the nested structure
getIds(obj);
console.log(ids);
// [2, 21, 22, 23, 231]
You could use a recursive function like this:
const myObj = obj = {
_id: 1,
children: [
{
id: 2,
children: [
{
id: 21,
children: [],
},
{
id: 22,
children: [],
},
{
id: 23,
children: [
{
id: 231,
children: [],
}
]
}
]
},
{
id: 3,
children: [
{
id: 31,
children: [],
},
{
id: 32,
children: [],
isCriteria: true
},
{
id: 33,
isCriteria: true
}
]
}
]
}
var idArray = []
function func(obj) {
idArray.push(obj._id ? obj._id : obj.id)
if (!obj.children) {
return
}
obj.children.forEach(child => func(child))
}
func(myObj)
console.log(idArray)
You could create a function (fill_ids) which loop every property of obj and push into an array (ids) the values of those with key _id or id, e.g.
let ids = [];
function fill_ids(obj) {
for (i in obj) {
if (i == '_id' || i == 'id') {
ids.push(obj[i]);
} else {
fill_ids(obj[i]);
}
}
}
let obj = {
_id: 1,
children: [{
id: 2,
children: [{
id: 21,
children: [],
}, {
id: 22,
children: [],
}, {
id: 23,
children: [{
id: 231,
children: [],
}]
}]
}, {
id: 3,
children: [{
id: 31,
children: [],
}, {
id: 32,
children: [],
isCriteria: true
}, {
id: 33,
isCriteria: true
}]
}]
};
fill_ids(obj);
console.log(ids);
you may use flatMap
see another example with flatDeep
let obj = {
_id: 1,
children: [
{
id: 2,
children: [
{
id: 21,
children: [],
},
{
id: 22,
children: [],
},
{
id: 23,
children: [
{
id: 231,
children: [],
}
]
}
]
},
{
id: 3,
children: [
{
id: 31,
children: [],
},
{
id: 32,
children: [],
isCriteria: true
},
{
id: 33,
isCriteria: true
}
]
}
]
}
function flatDeep(o) {
return [o.id||o._id].concat( (o.children||[]).flatMap(flatDeep) );
};
console.log(flatDeep(obj));
you could remove the ||o._id and o.children||[] depending on whether your sample input was correct or approximative :)

Is there a good way to combine array and object in JavaScript?

There is an object and an array.
list: [
{
oldData: {
title: 'abc',
id: 1,
date: '1982-09-30',
budget: 250000,
},
newData: [
{
key: 1,
data: null,
value: 5,
},
{
key: 2,
data: null,
value: 22,
},
...
],
},
{
oldData: {
title: 'blablablaaaaa',
id: 2,
date: '2012-02-23',
budget: 350000,
},
newData: [
{
key: 1,
data: null,
value: 35,
},
{
key: 2,
data: null,
value: 41,
},
...
],
},
... some more datas...
]
as above, There is more data of the same type.
I need to use oldData and newData together, so I want to combine the two.
How can I combine oldData and newData so that there are multiple sets of oldData and newData pairs?
for example, [{ combineData: {...} }, { combineData: {...} }, ... }] here.
I know how to combine array and array, object and object, but I do not know how to do that.
Is there any good solution?
Your desired result is unclear, but you did say you wanted old/new pairs. This answer is different than the others in that it produces an array of combined data objects made of old/new pairs, where the oldData values are duplicated in order to appear alongside each corresponding newData value within its list item.
your original data after the first question update:
let list = [
{
oldData: { title: 'abc', id: 1, date: '1982-09-30', budget: 250000 },
newData: [
{ key: 1, data: null, value: 5 },
{ key: 2, data: null, value: 22 },
//...
],
},
{
oldData: { title: 'blablablaaaaa', id: 2, date: '2012-02-23', budget: 350000 },
newData: [
{ key: 1, data: null, value: 35 },
{ key: 2, data: null, value: 41 },
//...
],
},
//... some more datas...
];
This code maps each {old,new[]} list item into arrays of pairs [{old,new}, {old,new}, ...] that are combined in the final reduce() call:
var combinedDatas = list
.map(listItem => listItem.newData.map(newItem => ({
oldData: listItem.oldData,
newData: newItem
})))
.reduce();
console.log(JSON.stringify(oldNewCombos, null, 4));
produces a list of denormalized pairs:
[
{ list[0].oldData, list[0].newData[0] },
{ list[0].oldData, list[0].newData[1] },
//...rest of list[0] oldData with newData[n] combos
{ list[1].oldData, list[1].newData[0] },
{ list[1].oldData, list[1].newData[1] },
//...rest of list[1] oldData with newData[n] combos
{ list[2].oldData, list[2].newData[0] },
{ list[2].oldData, list[2].newData[1] },
//...rest of list[2] oldData with newData[n] combos
//...
]
You can use map() on the array. And use Object.assign() and spread operator to combine all the properties of all the elements in newData into one object.
const arr = [
{
oldData: {
a:10,
b:20
},
newData: [
{
c:30,
d:40
},
{
e:50,
f:60
}
],
}
]
const res = arr.map(x => ({combinedData:{...x.oldData, ...Object.assign({}, ...x.newData)}}))
console.log(res)
You can map over the array and use object destructuring (...object) to create a new, combined object:
const data = [
{
oldData: {
foo: 'lorem',
},
newData: {
bar: 'ipsum',
},
},
{
oldData: {
foo: 'dolor',
},
newData: {
bar: 'sit amet',
},
},
];
const combined = data.map(record => ({...record.oldData, ...record.newData}));
console.log(combined);
This will overwrite duplicate keys however, so something like:
{
oldData: {
message: 'a',
},
newData: {
message: 'b',
},
}
will become:
{
message: 'b',
}

Categories