Create an array of objects recursively based in array of objects - javascript

I have an array of objects like this:
myArr = [
{ "id": "aaa.bbb" },
{ "id": "aaa.ccc" },
{ "id": "111.222" },
{ "id": "111.333" },
]
My goal is to be able to have a new array for every part of the Id, while nesting the old array. Like this:
newArray = [
{
"id": "aaa",
"children": [{ "id": "aaa.bbb" }]
},
{
"id": "aaa",
"children": [{ "id": "aaa.ccc" }]
},
{...}
]
The idea is to be able to do It with multiple substrings if there is a bigger Id

You could use map to iterate through the array and mutate the objects in place
myArr = [ { "id": "aaa.bbb" }, { "id": "aaa.ccc" }, { "id": "111.222" }, { "id": "111.333" }, ]
result=myArr.map((o)=>({["id"]:o.id.split(".")[0],["children"]:[o]}))
console.log(result)
alternatively you could use reduce
myArr = [ { "id": "aaa.bbb" }, { "id": "aaa.ccc" }, { "id": "111.222" }, { "id": "111.333" }, ]
result=myArr.reduce((acc,curr)=>acc=[...acc,{["id"]:curr.id.split(".")[0],["children"]:[curr]}],[])
console.log(result)

Use Array.prototype.map.
const newArray = myArr.map( function( e ) {
const oldId = e.id;
const newElement = {
id: oldId.split( '.' )[0],
children: [ e ]
};
return newElement
} );
Simplified:
const newArray = myArr.map( function( e ) {
return {
id: e.id.split( '.' )[0],
children: [ e ]
};
} );
Further:
const newArray = myArr.map( e => { id: e.id.split( '.' )[0], children: [ e ] } );

Related

JavaScript - filter in loop, create duplicate

I want to filter an array with another array in order to know if there are new people.
const people = [
{ "name": "jerry" },
{ "name": "tom" },
{ "name": "alex" }
]
const newList = [
{ "name": "bran" },
{ "name": "jerry" },
{ "name": "john" }
]
const new_people = []
for (const pp of people) {
let result = newList.filter(newL => newL.name != pp.name)
if (result) {
new_people.push(result)
}
}
console.log(new_people)
This is the result:
[
[ { name: 'bran' }, { name: 'john' } ],
[ { name: 'bran' }, { name: 'jerry' }, { name: 'john' } ],
[ { name: 'bran' }, { name: 'jerry' }, { name: 'john' } ]
]
But I'm looking for:
[ { name: 'bran' }, { name: 'john' } ]
I would like to avoid the loop because it makes duplicate in the result but I don't know how I can't do it without the loop.
First make a temporary array of people name:
const peopleNames = people.map(pp => pp.name);
Then the peopleNames will be as follows:
['jerry', 'tom', 'alex']
Now filter the new people from the newList:
const newPeople = newList.filter(pp => !peopleNames.includes(pp.name));
The newPeople will be an array of objects that you are looking for.
[{name: 'bran'}, {name: 'john'}]
const people = [
{ "name": "jerry" },
{ "name": "tom" },
{ "name": "alex" }
]
const newList = [
{ "name": "bran" },
{ "name": "jerry" },
{ "name": "john" }
]
const output = newList.filter(a => people.filter(x => x.name == a.name).length == 0);
console.log('By USing Filter', output);
//filter the newList and retain those object, which are not present in the people
//Way 2: By using some
//const output2 = newList.filter(a => !people.some(x => x.name == a.name));
//console.log('By Using Some', output2);
You can use Array's reduce method to get the desired result:
const new_people = newList.reduce((accVal, e) =>
(people.map(p => p.name).includes(e.name))
? accVal
: accVal.concat({ "name": e.name } ),
[ ] )

Filter array with objects based on another array

How do I filter such array:
const recipes = [
{
"id": 1,
"name": "Boiled Egg",
"ingredients": [
"egg",
"water"
],
},
{
"id": 2,
"name": "Pancakes",
"ingredients": [
"egg",
"milk",
"flour"
],
},
{
"id": 3,
"name": "Bread",
"ingredients": [
"flour",
"water",
"salt"
],
},
]
based on elements in such array
const selectedIngredients = ["milk", "salt"]
I played with combination of array.filter, array.some as show in Check if an array contains any element of another array in JavaScript but can't get it working properly
I want to get recipes with id 2 and 3 as a result
You can set the condition of the filter to whether selectedIngredients includes an item that is included in the item's ingredients property:
const recipes=[{id:1,name:"Boiled Egg",ingredients:["egg","water"]},{id:2,name:"Pancakes",ingredients:["egg","milk","flour"]},{id:3,name:"Bread",ingredients:["flour","water","salt"]}];
const selectedIngredients = ["milk", "salt"]
const result = !selectedIngredients.length ? [...recipes] : recipes.filter(e => selectedIngredients.some(f => e.ingredients.includes(f)))
console.log(result)
const recipes = [
{
"id": 1,
"name": "Boiled Egg",
"ingredients": [
"egg",
"water"
],
},
{
"id": 2,
"name": "Pancakes",
"ingredients": [
"egg",
"milk",
"flour"
],
},
{
"id": 3,
"name": "Bread",
"ingredients": [
"flour",
"water",
"salt"
],
},
]
const selectedIngredients = ["flour", "water"]
const selectAny = (list, filter) =>
list.filter(e => e.ingredients.some(i => filter.includes(i)));
const selectAll = (list, filter) =>
list.filter(e => filter.every(i => e.ingredients.includes(i)));
console.log('any', selectAny(recipes, selectedIngredients));
console.log('all', selectAll(recipes, selectedIngredients));
I would do it like this
const recipes = [
{
id: 1,
name: 'Boiled Egg',
ingredients: ['egg', 'water'],
},
{
id: 2,
name: 'Pancakes',
ingredients: ['egg', 'milk', 'flour'],
},
{
id: 3,
name: 'Bread',
ingredients: ['flour', 'water', 'salt'],
},
];
//
const doRebuild = (selectedIngredients)=>{
const build = [];
for(const two of selectedIngredients){
for(const one of recipes){
if(one.ingredients.some((a)=>two === a))build.push(one);
}
}
return build.length > 0 ? build : ['No recipes'];
};
//
const content1 = doRebuild(['milk2', 'salt2']);
const content2 = doRebuild(['milk', 'salt']);
console.log(content1);
console.log(content2);

Remove JSON attributes if not found in defined array

I need to remove attribute from the meta if it's not exist in att
for example : cardNo is not existing in the att
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
Expected output:
[
{
"id": 1,
"name": "test",
},
{
"id": 2,
"name": "test2"
}
];
for(let data of meta){
for (let key of Object.keys(data)) {
if (arr.indexOf(key) == -1) {
delete obj[key];
}
} }
Use Ramda.js (https://ramdajs.com/docs/) to make it easier:
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
]
const onlyAtts = map(pick(att), meta)
i think this is the answer for your question.
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
let newMeta = meta.map((d) => {
let obj = {};
att.forEach((currentAtt) => {
if(d.hasOwnProperty(currentAtt)) {
obj[currentAtt] = d[currentAtt];
}
});
return obj;
});
console.log(newMeta);
You can easily achieve this using map and reduce.
const att = ["id", "name", "class"];
const meta = [
{
id: 1,
name: "test",
cardNo: 23,
},
{
id: 2,
name: "test2",
cardNo: 232,
},
];
const result = meta.map((obj) => {
const perfectObj = att.reduce((acc, curr) => {
if (obj[curr]) {
acc[curr] = obj[curr];
}
return acc;
}, {});
return perfectObj;
});
console.log(result);
This is also works
const att = ['id', 'name','class'];
const meta = [
{
"id": 1,
"name": "test",
"cardNo": 23
},
{
"id": 2,
"name": "test2",
"cardNo": 232
}
];
function compare(meta, fields) {
meta.map(object => {
let dataKeys = Object.keys(object);
dataKeys.forEach(element => {
if(fields.indexOf(element) < 0) {
delete object[element];
}
});
});
}
compare(meta, att);
console.log(meta);

Combining same objects in json array javascript

I have this array:
[{ "id": 1, "myId": "100", "name": "amey" }, { "id": 2, "myId": "100", "name": "anuj" }, { "id": 3, "myId": "101", "name": "suraj" }, { "id": 4, "myId": "101", "name": "suraj h" }]
I want output like this:
[{ "id": 1, "myId": "100", "name": ["amey", "anuj"] }, { "id": 3, "myId": "101", "name": ["suraj", "suraj h] }]
How can I do this using javascript
for (var i = 0; i < myarray.length; i++) {
//And loop again for duplicate data
for (var j = i + 1; j < myarray.length; j++) {
if (
myarray[i].VENDOR_ID == myarray[j].VENDOR_ID &&
myarray[i].ORDER_ID === myarray[j].ORDER_ID
) {
var tmp = myarray[j].NAME;
console.log(tmp);
myarray[j].NAME = [];
myarray[j].NAME.push(tmp);
myarray[j].NAME.push(myarray[i].NAME);
myarray[i] = {};
}
}
}
You can use an array reduce into an object and return the array of values. Reduce into an object using the myId property as the key to group by. Shallow copy any existing state and and name array, appending the new name value from the current element.
Object.values(
input.reduce(
(acc, { id, myId, name }) => ({
...acc,
[myId]: {
...(acc[myId] || { id, myId }),
name: [...(acc[myId]?.name || []), name]
}
}),
{}
)
const input = [
{ id: 1, myId: "100", name: "amey" },
{ id: 2, myId: "100", name: "anuj" },
{ id: 3, myId: "101", name: "suraj" },
{ id: 4, myId: "101", name: "suraj h" }
];
const res = Object.values(
input.reduce(
(acc, { id, myId, name }) => ({
...acc,
[myId]: {
...(acc[myId] || { id, myId }),
name: [...(acc[myId]?.name || []), name]
}
}),
{}
)
);
console.log(JSON.stringify(res));
You can use Array.prototype.reduce():
const arr1 = [{
"id": 1,
"myId": "100",
"name": "amey"
}, {
"id": 2,
"myId": "100",
"name": "anuj"
}, {
"id": 3,
"myId": "101",
"name": "suraj"
}, {
"id": 4,
"myId": "101",
"name": "suraj h"
}]
const reduced = arr1.reduce((acc, item) => {
// 1. check if the 'acc' array already contains an item with the same 'myId' attribute
const itemIndex = acc.findIndex(it => it.myId === item.myId);
// 2. if there isn't any, push into the 'acc' array a copy of the item,
// with the 'name' property converted into an array of strings
// otherwise simply push the 'name' into the already existing item
if (itemIndex === -1) {
acc.push({
...item,
name: [item.name]
});
} else {
acc[itemIndex].name.push(item.name)
}
return acc;
}, []);
// test
console.log(reduced);

Update Object inside an array of objects with another object [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 3 years ago.
I'm writing a simple Vue app where an Array with Objects should be updated with an incoming object.
I start with this Object:
var arr =
[
{
"mainId": 1,
"parents": [
{
"parent": 1
},
{
"parent": 2
}
]
},
{
"mainId": 2,
"parents": [
{
"parent": 3
}
]
}
]
I want to Update the "parent" Array with the following Object:
var updateArray = {
"mainId": 2,
"parent": 9
}
var updatedArray =
[
{
"mainId": 1,
"parents": [
{
"parent": 1
},
{
"parent": 2
}
]
},
{
"mainId": 2,
"parents": [
{
"parent": 3
},
{
"parent": 9 // <-------------
}
]
}
]
What is the best way to achieve this?
You can look for the object using Array.find and it will give you a reference to the object inside the array, so when you update that object, it will be updated inside the array :
var arr = [{
mainId: 1,
parent: [{
parent: 1
},
{
parent: 2
}
]
},
{
mainId: 2,
parent: [{
parent: 3
}]
}
];
var updateArray = {
mainId: 2,
parent: 9
};
var obj = arr.find(o => o.mainId === updateArray.mainId);
obj.parent.push({
parent: updateArray.parent
})
console.log(arr);
You can achieve it by using native map function without any mutations:
const updatedArray = arr.map(obj => {
if (obj.mainId === givenMainId) {
const parent = obj.parent || []
return { ...obj, parent: [...parent, { parent: givenParentId }] };
}
return obj;
})
You can use find() to get the appropriate item by its mainId identifier and then use push() to add another object:
const arr =
[
{
"mainId": 1,
"parent": [
{
"parent": 1
},
{
"parent": 2
}
]
},
{
"mainId": 2,
"parent": [
{
"parent": 3
}
]
}
]
const id = 2
const obj = arr.find(({mainId}) => mainId === id)
obj.parent.push({ "parent": 9 })
console.log(arr)

Categories

Resources