How to join 2 array object using lodash - javascript

I want to join a with b using lodash here is my data
const a =
[ { id: 1, job: 'engineer' }
, { id: 2, job: 'police' }
, { id: 3, job: 'thief' }
]
const b =
[ { name: 'test1', score: 1, aId: [ 1, 2 ] }
, { name: 'test2', score: 3, aId: [ 1, 3 ] }
]
Here is my output that I want
const result =
[ { id: 1, job: 'engineer', score: [ {name: 'test1'}, {name: 'test2'} ] }
, { id: 2, job: 'police', score: [] }
, { id: 3, job: 'thief', score: [ {name: 'test 3'} ] }
]
this is what I try I'm using 2 map data and inside the second map I use include check between 2 arrays..
_.map(a, function(data:any) {
const name = _.map(b, function(dataB:any) {
// in here I check
const isValid = dataB.aId.includes(a.id)
if(isValid){
return {
name = dataB.name
}
}
})
return {
id: data.id
job: data.job
score: name
}
});
this method also work but is their any better method than using 2 map ?

Reduce b to a map of id to array of tests, and then map a, and take the relevant array from the map to create each object:
const a =
[ { id: 1, job: 'engineer' }
, { id: 2, job: 'police' }
, { id: 3, job: 'thief' }
]
const b =
[ { name: 'test1', score: 1, aId: [ 1, 2 ] }
, { name: 'test2', score: 3, aId: [ 1, 3 ] }
]
const bMap = b.reduce((acc, { name, aId }) => {
const nameObject = { name }
aId.forEach(id => {
if(!acc.has(id)) acc.set(id, [])
acc.get(id).push(nameObject)
})
return acc
}, new Map())
const result = a.map(o => ({ ...o, scores: bMap.get(o.id) }))
console.log(result)

Related

Filter out array using another array of objects

I am having two arrays
const selected = [];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
const result = []
I need to compare these two arrays and the result should only have the single entry instead of duplicates. In the above example result should have the following output.
Also items in the selected should be taken into consideration and should be in the beginning of the result
result = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
Also when the input is following
const selected = [ {id:5, name: "xyz" }];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
result = [[
{ id: 5, name: "xyz" },
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
Also when the input is following
const selected = [ {id:1, name: "abc" }, {id:4, name: "lmn" }];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
result = [[
{ id: 1, name: "abc" },
{ id: 4, name: "lmn" }
{ id: 2, name: "def" }
];
Note the comparison should be made using name field
Code that I tried
const res = [...(selected || [])].filter((s) =>
current.find((c) => s.name === c.name)
);
Sandbox: https://codesandbox.io/s/nervous-shannon-j1vn5k?file=/src/index.js:115-206
You could get all items and filter the array by checking the name with a Set.
const
filterBy = (key, s = new Set) => o => !s.has(o[key]) && s.add(o[key]),
selected = [{ id: 1, name: "abc" }, { id: 1, name: "lmn" }],
current = [{ id: 1, name: "abc" }, { id: 2, name: "def" }],
result = [...selected, ...current].filter(filterBy('name'));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Loop through selected, and if there is no object in current with a name that matches the name of the object in the current iteration push it into current.
const selected=[{id:1,name:"abc"},{id:6,name:"def"},{id:4,name:"lmn"}];
const current=[{id:1,name:"abc"},{id:2,name:"def"}];
for (const sel of selected) {
const found = current.find(cur => cur.name === sel.name);
if (!found) current.push(sel);
}
console.log(current);
This is a good use for .reduce, avoids multiple loops/finds and doesn't need filtering with side-effects.
const selected = [ {id:1, name: "abc" }, {id:4, name: "lmn" }];
const current = [
{ id: 1, name: "abc" },
{ id: 2, name: "def" }
];
const result = Object.values(
[...selected, ...current].reduce((obj, item) => {
obj[item.name] = obj[item.name] || item;
return obj;
}, {})
)
console.log(result);

How to check array of objects based on ID and add new property in JavaScript

I have two array of objects arr1 and arr2
if arr1 and arr2 id matches, then push arr1 property name to arr2 in javascript
var arr1 = [
{id: 1, name : "Helena"},
{id: 2, name : "John"}
]
var arr2 = [{
country: "MY",
details: [{
mode: "parttime",
members:[{id:1}, {id: 2}]
}]
}]
Expected Output:
[{
country: "MY",
details:[{
mode: "parttime",
members: [
{id:1, name: "Helena"},
{id: 2, name: "john"}
]
}]
}]
Please try:
var arr1 = [
{
id: 1,
name: "Helena",
},
{
id: 2,
name: "John",
},
];
var arr2 = [
{
country: "MY",
details: [
{
mode: "parttime",
members: [
{
id: 1,
},
{
id: 2,
},
],
},
],
},
];
function getCountriesWithMemberNames(membersArr, countriesArr) {
// mapping each country obj in the array to a modified country
return countriesArr.map((country) => {
return {
...country, // take all existing country info
// modify country.details, mapping it to a new object
details: country.details.map((detail) => {
return {
...detail, // take all details
// modying members
members: detail.members.map((member) => {
const memberObj = { ...member };
// check if name exists for this member
const name = membersArr.find((i) => i.id === member.id).name;
if (name) {
memberObj.name = name;
}
return memberObj;
}),
};
}),
};
});
}
console.log(getCountriesWithMemberNames(arr1, arr2));

mapping two arrays of equivalent length by object attributes javascript [duplicate]

This question already has answers here:
Merge two array of objects based on a key
(23 answers)
Closed 1 year ago.
I have two arrays:
Array 1:
[
{
name: 'Bob',
traits: {
id: 1
}
}, {
name: 'Karl',
traits: {
id: 2
}
}, {
name: 'Joseph',
traits: {
id: 3
}
}
]
Array 2:
[
{
name: 'Karl',
user_id: 2,
dog: 'Rottweiler'
}, {
name: 'Joseph',
user_id: 3,
dog: 'Poodle'
}, {
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
]
Desired outcome:
I want to be able to merge the second array into the first array by finding what element user_id matches with id and then adding the object to array.
For example:
array 1 obj
{
name: 'Bob',
traits: {
id: 1
}
}
Since the id matches with array 2 obj user_id:
{
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
Final outcome will be:
{
name: 'Bob',
traits: {
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
}
arr2.forEach((obj) => {
const idx = arr1.findIndex((o) => o.traits.id === obj.user_id);
if (idx !== -1) {
arr1[idx] = { ...arr1[idx], traits: { ...obj } }
}
})
console.log(arr1[0]) // { name: 'Bob', traits: { name: 'Bob', user_id: 1, dog: 'Puppy' } }
Turn the second array into a map keyed by user_id, and then iterate the first array. Find the corresponding object in the map, and spread the matching object value into the traits property:
let arr1 = [{name: 'Bob',traits: {id: 1}},{name: 'Karl',traits: {id: 2}},{name: 'Joseph',traits: {id: 3}}];
let arr2 = [{name: 'Karl', user_id: 2,dog: 'Rottweiler'},{name: 'Joseph', user_id: 3,dog: 'Poodle'},{name: 'Bob',user_id: 1,dog: 'Puppy'}];
let map = new Map(arr2.map(item => [item.user_id, item]));
let result = arr1.map(item => {
let traits = map.get(item.traits.id);
return traits ? { ...item, traits} : item;
});
console.log(result);
As lookup in a map has an amortised time complexity of O(1), this is more efficient than finding the key in the array on every iteration (like with calling find).
You can easily achieve this result using map and find. Just map over the first array and find the element with obj.traits.id in the arr2. then return the desired result.
const arr1 = [
{
name: "Bob",
traits: {
id: 1,
},
},
{
name: "Karl",
traits: {
id: 2,
},
},
{
name: "Joseph",
traits: {
id: 3,
},
},
];
const arr2 = [
{
name: "Karl",
user_id: 2,
dog: "Rottweiler",
},
{
name: "Joseph",
user_id: 3,
dog: "Poodle",
},
{
name: "Bob",
user_id: 1,
dog: "Puppy",
},
];
const result = arr1.map((obj) => {
const { name, traits } = obj;
const isExist = arr2.find((o) => o.user_id === traits.id);
if (isExist) {
return { name, traits: { ...isExist } };
}
return obj;
});
console.log(result);
let a = [
{
name: 'Bob',
traits: {
id: 1
}
}, {
name: 'Karl',
traits: {
id: 2
}
}, {
name: 'Joseph',
traits: {
id: 3
}
}
];
let b = [
{
name: 'Karl',
user_id: 2,
dog: 'Rottweiler'
}, {
name: 'Joseph',
user_id: 3,
dog: 'Poodle'
}, {
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
];
a.map(aobj =>{
let sameIdObj = b.find( bobj => bobj.user_id === aobj.traits.id )
sameIdObj && (aobj.traits = sameIdObj)
})
console.log(a);

How can I remove the name field from a json array?

I have a json array like this:
(3) [{…}, {…}, {…}]
0: {Id: 1, Name: "bask"}
1: {Id: 2, Name: "voll"}
2: {Id: 3, Name: "badminton"}
I want to turn it into something like this:
{1:"bask",2:"voll",3:"badminton"}
You can use reduce to loop through array and build a object of desired key/value pair
let data = [{Id: 1, Name: "bask"},{Id: 2, Name: "voll"},{Id: 3, Name: "badminton"}]
let output = data.reduce((op, {Id, Name}) => {
op[Id] = Name
return op
},{})
console.log(output)
You could take Object.fromEntries with the maped key/value pairs.
var array = [{ Id: 1, Name: "bask" }, { Id: 2, Name: "voll" }, { Id: 3, Name: "badminton" }],
object = Object.fromEntries(array.map(({ Id, Name }) => [Id, Name]));
console.log(object);
You can check out the reduce() function!
let array = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
];
console.log(_.reduce(array, function(result, obj){
result[obj.Id] = obj.Name;
return result;
}, {}));
You can checkout lodash an awesome library with many other such utilities!
You can do this with reduce():
var a = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
]
b = a.reduce((acc, item) => {
acc[item.Id] = item.Name;
return acc;
}
console.log(b);
You can do it in different ways, here one of them.
let dataArray = [
{id: 1, name: 'bask'},
{id: 2, name: 'voll'},
{id: 3, name: 'badminton'}
]
let ouputObject = {}
dataArray.map(data => {
ouputObject[`${data.id}`] = data.name
})
console.log(ouputObject)
outputObject will be
Object {
1: "bask",
2: "voll",
3: "badminton"
}
Using Array.reduce() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var reduceObj = arr.reduce(function(result, currentElement) {
result[currentElement.Id] = currentElement.Name;
return result;
}, {});
console.log(reduceObj);
Using Array.map() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var mapObject = {}
arr.map(obj => {
mapObject[obj.Id] = obj.Name
})
console.log(mapObject);

check the difference between two arrays of objects in javascript [duplicate]

This question already has answers here:
How to get the difference between two arrays of objects in JavaScript
(22 answers)
Closed 1 year ago.
I need some help. How can I get the array of the difference on this scenario:
var b1 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' },
{ id: 2, name: 'pablo' },
{ id: 3, name: 'escobar' }
];
var b2 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' }
];
I want the array of difference:
// [{ id: 2, name: 'pablo' }, { id: 3, name: 'escobar' }]
How is the most optimized approach?
I´m trying to filter a reduced array.. something on this line:
var Bfiltered = b1.filter(function (x) {
return x.name !== b2.reduce(function (acc, document, index) {
return (document.name === x.name) ? document.name : false
},0)
});
console.log("Bfiltered", Bfiltered);
// returns { id: 0, name: 'john' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ]
Thanks,
Robot
.Filter() and .some() functions will do the trick
var b1 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' },
{ id: 2, name: 'pablo' },
{ id: 3, name: 'escobar' }
];
var b2 = [
{ id: 0, name: 'john' },
{ id: 1, name: 'mary' }
];
var res = b1.filter(item1 =>
!b2.some(item2 => (item2.id === item1.id && item2.name === item1.name)))
console.log(res);
You can use filter to filter/loop thru the array and some to check if id exist on array 2
var b1 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ];
var b2 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }];
var result = b1.filter(o => !b2.some(v => v.id === o.id));
console.log(result);
Above example will work if array 1 is longer. If you dont know which one is longer you can use sort to arrange the array and use reduce and filter.
var b1 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ];
var b2 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }];
var result = [b1, b2].sort((a,b)=> b.length - a.length)
.reduce((a,b)=>a.filter(o => !b.some(v => v.id === o.id)));
console.log(result);
Another possibility is to use a Map, allowing you to bring down the time complexity to O(max(n,m)) if dealing with a Map-result is fine for you:
function findArrayDifferences(arr1, arr2) {
const map = new Map();
const maxLength = Math.max(arr1.length, arr2.length);
for (let i = 0; i < maxLength; i++) {
if (i < arr1.length) {
const entry = arr1[i];
if (map.has(entry.id)) {
map.delete(entry.id);
} else {
map.set(entry.id, entry);
}
}
if (i < arr2.length) {
const entry = arr2[i];
if (map.has(entry.id)) {
map.delete(entry.id);
} else {
map.set(entry.id, entry);
}
}
}
return map;
}
const arr1 = [{id:0,name:'john'},{id:1,name:'mary'},{id:2,name:'pablo'},{id:3,name:'escobar'}];
const arr2 = [{id:0,name:'john'},{id:1,name:'mary'},{id:99,name:'someone else'}];
const resultAsArray = [...findArrayDifferences(arr1,arr2).values()];
console.log(resultAsArray);

Categories

Resources