How to merge two arrays with new property in javascript - javascript

How to merge two arrays in javascript.I tried but not working. How to add new property like details and how to merge in single array
Demo: https://stackblitz.com/edit/js-6cfbaw
Example:
var array1 = [
{
id: 1,
name: "Zohn",
},
];
var array2 = [
{
name: "Zohn",
address: "Test1",
},
{
name: "Zohn Peter",
address: "Test2",
},
{
name: "Peter Mark",
address: "Test3",
},
];
var array3 = [...array1, ...array2];
Output array3 should be :
[
{
id: 1,
name: "Zohn",
details: [
{
name: "Zohn Zeo",
address: "Test1",
},
{
name: "Zohn Peter",
address: "Test2",
},
{
name: "Peter Mark",
address: "Test3",
},
],
},
];

No need to merge the arrays, you are just adding an attribute to the first element of array1.
var array1 = [
{
id:1,
name:"Zohn"
}
]
var array2 = [
{
name:"Zohn",
address:"Test1"
},
{
name:"Zohn Peter",
address:"Test2"
},
{
name:"Peter Mark",
address:"Test3"
}
]
array1[0]['details'] = array2
console.log(array1)

I hope this piece of code helps you.
var array1 =[];
var itemOfArray= {
id:1,
name:"Zohn" ,
details: [ ]
};
var array2 = [
{
name:"Zohn",
address:"Test1"
},
{
name:"Zohn Peter",
address:"Test2"
},
{
name:"Peter Mark",
address:"Test3"
}
]
itemOfArray['details']=array2;
array1.push(itemOfArray);
console.log(array1);

Try this example
var array1 = [
{
id: 1,
name: "Zohn",
},
];
var array2 = [
{
name: "Zohn",
address: "Test1",
},
{
name: "Zohn Peter",
address: "Test2",
},
{
name: "Peter Mark",
address: "Test3",
},
];
const output = array1.map((entry) => ({ ...entry, details: [...array2] }));
console.dir(output, { depth: null, color: true });

If you want to merge details, you have to keep a reference for each record of array1 in array2 and then merge as shown below.
var array1=[
{
id:1,
name:"Zohn"
}
];
var array2=[
{
array1Id: 1,
name:"Zohn",
address:"Test1"
},
{
array1Id: 1,
name:"Zohn Peter",
address:"Test2"
},
{
array1Id: 1,
name:"Peter Mark",
address:"Test3"
}
];
var array3 = [];
array1.forEach((entry) => {
array3.push(
{
id: entry.id,
name: entry.name,
details: array2.filter((value) => {
return value.array1Id == entry.id;
})
}
);
});
console.log(array3);

Related

Append/Add the property to array of objects if match found using javascript

I have two array of objects, in which if id and aid property values match then append the property code to arr1 and return the result
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
Expected result:
var arr1 = [
{ id: 1, name: "xxx", cn: "IN", code: 'finance'},
{ id: 2, name: "yyy", cn: "MY", code: 'others'},
{ id: 3, name: "zzz", cn: "SG", code: ''},
]
I tried
var result = arr1.map(e=> ({
...e,
code: arr2.map(i=>i.code)
})
You can do what you require with a loop over arr1 looking for matches in arr2 using filter(). This will add the code property to the existing arr1 array without creating a new array instance.
Note that this logic assumes that there will only ever be 0 or 1 matches in arr2.
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
arr1.forEach(o1 => o1.code = arr2.filter(o2 => o2.aid === o1.id)[0]?.code || '');
console.log(arr1);
I am not sure if this is the most optimal solution but this definitely works for your case:
let result = arr1.map((outerObj) => {
// First we try to find the index of the matching object
let index = arr2.findIndex((innerObj) => {
return outerObj.id == innerObj.aid;
});
// In case of no match, set case as "" as per requirement
if(index == -1) {
outerObj.code = "";
return outerObj;
}
// If a match is found, then combine the two objects.
let mergedObj = { ...outerObj, ...arr2[index]};
// aid is not needed in the result, Who wants aids anyway?
delete mergedObj.aid;
return mergedObj;
});
If not more optimal, then definitely there could be smaller code but I think the code should be clear and readable rather than being smaller.
First, massage the data into a format for fast manipulation; then manipulate.
The following:
Puts every item in arr2 into a map, keyed on aid
Enumerates arr1 once, looking into the map for each item to see if there is a corresponding code
Performance: O(N).
var arr1= [
{id:1, name: "xxx", cn: "IN"},
{id:2, name: "yyy", cn: "MY"},
{id:3, name: "zzz", cn: "SG"} ]
var arr2 = [
{ aid: 1, code: "finance"},
{ aid: 2, code: "others"},
{ aid: 4, code: "finance"},
{ aid: 5, code: "product"} ]
const map = arr2.reduce((p,c) => p.set(c.aid, c), new Map)
arr1.forEach((i) => i.code = map.get(i.id)?.code || '')
console.log(arr1)
You need to first find matching item in arr2 and them create the composed item.
Try like this:
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
];
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
];
const result = arr1.map((item) => {
const match = arr2.find((o) => o.aid === item.id);
return { ...item, code: match ? match.code : '' };
});
console.log(result);
we can get like this too
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
const fun = (ar, ar2)=>{
const getResult = ar.map((e)=> {
const Data ={
id : e.id,
name : e.name,
cn : e.cn,
code : ar2.find((e2)=> e2.aid===e.id)?.code || ""
}
return Data;
})
return getResult
}
console.log(fun(arr1, arr2))
we can usefind method too
var arr1 = [
{ id: 1, name: "xxx", cn: "IN" },
{ id: 2, name: "yyy", cn: "MY" },
{ id: 3, name: "zzz", cn: "SG" },
]
var arr2 = [
{ aid: 1, code: "finance" },
{ aid: 2, code: "others" },
{ aid: 4, code: "finance" },
{ aid: 5, code: "product" },
]
arr1.forEach(e => e.code = arr2.find(d => d.aid === e.id)?.code || '');
console.log(arr1);

Lodash how to group array of objects by array of values?

I want to group an array of objects based on a property which has an array of values,and i want to return a group for each individual value,not only for the whole array.
For example :
let crew = [
{
name:"john",
job :["electrician","carpenter"]
},
{
name: "bill",
job: ["electrician"]
},
{
name: "mark",
job: [ "carpenter"]
}
]
let groupedCrew = _.groupBy(crew,"job")
console.log(groupedCrew)
/*
carpenter:
[
{
job:
[
carpenter
],
name:
"mark"
}
],
electrician:
[
{
job:
[
"electrician"
],
name:
"bill"
}
],
electrician, carpenter:
[
{
job:
[
"electrician",
"carpenter"
],
name:
"john"
}
]
}
*/
In this example i want "john" to also appear in "electrician" group.
Any ideas ?
Once again let's group something using reduce
Here's the basic structure (plus the solution)
let crew = [{
name: "john",
job: ["electrician", "carpenter"]
},
{
name: "bill",
job: ["electrician"]
},
{
name: "mark",
job: ["carpenter"]
}
];
var obj = crew.reduce(function(agg, item) {
// grouping logic below this line
item.job.forEach(function(job) {
agg[job] = agg[job] || []
// agg[job].push (item);
// lets push only name so we can see output
agg[job].push(item.name)
})
// grouping logic above this line
return agg
}, {})
console.log(obj)
use custom .reduce() function
there is no need for lodash
const crew = [
{
name: 'john',
job: ['electrician', 'carpenter'],
},
{
name: 'bill',
job: ['electrician'],
},
{
name: 'mark',
job: ['carpenter'],
},
];
const groupedCrew = crew.reduce((groupedCrew, person) => {
person.job.forEach(job => {
if (!groupedCrew[job]) groupedCrew[job] = [];
groupedCrew[job].push(person);
});
return groupedCrew;
}, {});
console.log(JSON.stringify(groupedCrew, null, 4));

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)

Subset Json object in Javascript

Given an array of json object like this below, (the json object such as "name2" and "name4" will definitely have only one key-value)
[
{
abc: 123,
id: '18263322',
name: 'name1'
},
{ name: 'name2' },
{
abc: 456,
id: '18421634',
name: 'name3'
},
{ name: 'name4' }
]
How can I subset this so that I have two array of json objects:
[
{
abc: 123,
id: '18263322',
name: 'name1'
},
{
abc: 456,
id: '18421634',
name: 'name3'
}
]
and
[
{ name: 'name2' },
{ name: 'name4' }
]
You can use reduce here
const arr = [
{
abc: 123,
id: "18263322",
name: "name1",
},
{ name: "name2" },
{
abc: 456,
id: "18421634",
name: "name3",
},
{ name: "name4" },
];
const [single, multiple] = arr.reduce((acc, curr) => {
Object.keys(curr).length === 1 ? acc[0].push(curr) : acc[1].push(curr);
return acc;
},[[], []]
);
console.log(single);
console.log(multiple);
You can also do something like
const [single, multiple] = arr.reduce((acc, curr) => {
acc[Object.keys(curr).length === 1 ? 0 : 1].push(curr);
return acc;
},[[], []]);
using filter
const arr = [
{
abc: 123,
id: "18263322",
name: "name1",
},
{ name: "name2" },
{
abc: 456,
id: "18421634",
name: "name3",
},
{ name: "name4" },
];
const single = arr.filter((o) => Object.keys(o).length === 1);
const multiple = arr.filter((o) => Object.keys(o).length !== 1);
console.log(single);
console.log(multiple);

Search/Filter nested Array Javascript/Lodash

For my React.js project I would like to create a search-filter of a nested Array. Users will search with an input-field.
var dataExample = [
{
type: "human", details: [
{id: 1, name: "Peter", description: "friendly, black-hair"},
{id: 5, name: "Susan", description: "blond"}
]
},
{
type: "animal", details: [
{id: 2, name: "Will", description: "lazy, cute"},
{id: 3, name: "Bonny", description: "beautiful"}
]
}
];
In my search-input-field I want to look for "name" or something in "description". The data structure of the array should remain the same.
The output when I'm searching for "friendly" or "Peter" should be:
[
{
type: "human", details: [
{id: 1, name: "Peter", description: "friendly, black-hair"}
]
}
];
Now I tried something like this:
let myfilter = dataExample.filter((data) => {
data.details.filter((items) => {
return (items.type.indexOf("human") !== -1 || //input of user
items.description.indexOf("friendly"))
})
})
Unfortunately, this is not how it works. Can anybody help me? Lodash would be no problem, too. Thank you so much.
You can use array#reduce with array#filter and to check for your word you can use string#incldues.
const dataExample = [ { type: "human", details: [ {id: 1, name: "Peter", description: "friendly, black-hair"}, {id: 5, name: "Susan", description: "blond"} ] }, { type: "animal",details: [ {id: 2, name: "Will", description: "lazy, cute"}, {id: 3, name: "Bonny", description: "beautiful"} ] } ],
term = 'Peter',
result = dataExample.reduce((r, {type,details}) => {
let o = details.filter(({name,description}) => name.includes(term) || description.includes(term));
if(o && o.length)
r.push({type, details : [...o]});
return r;
},[]);
console.log(result);
Here are some examples without lodash.
var dataAll = [
{
type: "human",
details: [
{id: 1, name: "Peter", description: "friendly, black-hair"},
{id: 5, name: "Susan", description: "blond"}
]
},
{
type: "animal",
details: [
{id: 2, name: "Will", description: "lazy, cute"},
{id: 3, name: "Bonny", description: "beautiful"}
]
}
];
var entryTypeFilter = data => data.type.indexOf("hum") !== -1;
var entryDetailDescFilter = data => data.description.indexOf("friend") !== -1;
var entryDetailsMapper = data => {
return {
type: data.type,
details: data.details.filter(entryDetailDescFilter)
};
};
var entryNoDetailsFilter = data => data.details && data.details.length !== 0;
var dataFilteredByType = dataAll.filter(entryTypeFilter);
var dataFilteredByDesc = dataAll.map(entryDetailsMapper);
var dataFilteredByTypeAndDesc = dataAll.filter(entryTypeFilter).map(entryDetailsMapper);
var dataFilteredByDescTrimmingEmptyDetailEntries = dataAll.map(entryDetailsMapper).filter(entryNoDetailsFilter);
In modern javascript you might want to search on how to use the ... keyword for the mapping callback functions.

Categories