Find intersection of 2 arrays containing slightly different objects - javascript

I'm trying to find the intersection from 2 different arrays that contain slightly different objects.
For example:
const arr1 = [
{
"number":"1234",
"id":"34782",
"firstName":"John",
"lastName":"Smith",
"email":"test1#test.com",
},
{
"number":"1232",
"id":"34783",
"firstName":"Chad",
"lastName":"Baker",
"email":"test2#test.com",
}
];
const arr2 = [
{
"uuid":"0123",
"firstName":"John",
"lastName":"Smith",
"title":"Director"
},
{
"uuid":"0125",
"firstName":"Sam",
"lastName":"Hurst",
"title":"Manager"
}
]
const arr3 = arr1.filter(object => arr2.includes(object));
console.log(arr3);
I'm trying to create a new array that contains only the objects in arr1 where firstName and lastName values are the same in both arrays.
Desired result from above data:
arr3 = [
{
"number":"1234",
"id":"34782",
"firstName":"John",
"lastName":"Smith",
"email":"test1#test.com",
},
]
since this object's firstName and lastName match in both arr1 and arr2
Right now i have this.arr3 = this.arr1.filter(object => this.arr2.includes(object))
But because arr1 and arr2 contain different objects due to proper names, this doesn't work.

Try something like this:
const arr1 = [{
"number": "1234",
"id": "34782",
"firstName": "John",
"lastName": "Smith",
"email": "test1#test.com",
},
{
"number": "1232",
"id": "34783",
"firstName": "Chad",
"lastName": "Baker",
"email": "test2#test.com",
}
];
const arr2 = [{
"uuid": "0123",
"firstName": "John",
"lastName": "Smith",
"title": "Director"
},
{
"uuid": "0125",
"firstName": "Sam",
"lastName": "Hurst",
"title": "Manager"
}
]
const arr3 = arr1.filter(value =>
arr2.some(value2 =>
value.firstName === value2.firstName && value.lastName === value2.lastName
)
);
console.log(arr3);
Basically, use some instead of includes as this allows you to provide a predicate.

I think you can try this :
arr1.filter(item1 => (arr2.find(item2 => (item2.firstName == item1.firstName && item2.lastName == item1.lastName)) != undefined));
It uses the arr2.find function, to check if it contains some item with same firstName and lastName properties.

Related

How to get the object from array and make a new array from it

Here is the sample json data that I have:
a = [
{
"first_name": "Andrew",
"last_name": " ",
"job": "actor",
},
{
"first_name": "Andrew",
"last_name": "Petrov",
"job": "",
"contry": "Russia"
},
{
"first_name": "Andrew",
"last_name": "Petrov",
"contry": "Russia"
},
]
And I want to extract the single object from this array and make a new array from this object.
This is the sample output which I wants to get:
[
{
"first_name": "Andrew",
"last_name": "Petrov",
"job": "actor",
"contry": "Russia"
}
]
As simple as a[1]
[n] is the index of the array. Index starts at 0
If you mean to get an object in array in array, a[1][0]
I think this should get you to the result you want.
Basically what I am doing is using the array.reduce method to iterate over all the objects in the input array and add the properties that are missing in the result object.
let a = [
{
"first_name": "Andrew",
"last_name": " ",
"job": "actor",
},
{
"first_name": "Andrew",
"last_name": "Petrov",
"job": "",
"contry": "Russia"
},
{
"first_name": "Andrew",
"last_name": "Petrov",
"contry": "Russia"
},
]
let result = a.reduce((prevValue, currentValue) => {for (let prop in currentValue) {
if (currentValue[prop].trim() && !prevValue[prop]) {
prevValue[prop] = currentValue[prop];
}
}
return prevValue;
}, {});
console.log(result);
In array you can get the n th item by providing the index number to it.
For example:
a = [10, 11, 12]
if you want's to get the 10 from this array you can do console.log(a[0]) which will log the 10 in your console. In here a[0] 0 is the index.
Same as in your condition: if you wants to get the object from your array you need to pass the index number of that particular object.
In your case, a[0] will return this output:
{
"first_name": "Andrew",
"last_name": " ",
"job": "actor",
}
Now the second case that you want is , you need to create a new array from this object.
There are number of ways to create an array, here is the simple one:
const myNewArray = [a[0]]
If you wrap your object with big brackets, it'll create a new array.
In your case, there are some fields which are missing in objects, to get that, there are number of ways that you can use like: reducer, map, forEach loop etc.
Here is the example with reducer:
let res = a.reduce((xs, cv) => {
for (let prop in cv) {
if (cv[prop].trim() && !xs[prop]) {
xs[prop] = cv[prop];
}
}
return xs;
}, {});
console.log("result is :", res)
1) You can easily achieve the result if you first filter out the properties of an object and then use Object.assign to get the desired result
One -liner solution
a.reduce((acc, curr) => Object.assign({},acc,Object.fromEntries(Object.entries(curr).filter(([k, v]) => v.trim() !== ""))),{});
const a = [
{
first_name: "Andrew",
last_name: " ",
job: "actor",
},
{
first_name: "Andrew",
last_name: "Petrov",
job: "",
contry: "Russia",
},
{
first_name: "Andrew",
last_name: "Petrov",
contry: "Russia",
},
];
const result = a.reduce((acc, curr) => Object.assign({},acc,Object.fromEntries(Object.entries(curr).filter(([k, v]) => v.trim() !== ""))),{});
console.log(result);

How to build a new Array of Objects from existing Array of Objects, filtered to match a list of keys

I have an array of objects, example:
[
{
"fName": "Jon",
"lName": "Doe",
"age": "30",
"shirtSize": "M"
},
{
"fName": "Jane",
"lName": "Foe",
"age": "25",
"shirtSize": "M"
},
...
]
I also have a list of keys, example:
["age", "shirtSize"]
I want to take the array of objects, and build a new array of objects that match the key list array, effectively filtering the array of objects to only have the key/value pairs I want. The above are examples, and the real datasets are of course more verbose. I've brute forced it in my algorithm below and as expected, it's not very performant at all, as a result of my loop within the map. My result is like:
[
{
"age": "30",
"shirtSize": "M"
},
{
"age": "25",
"shirtSize": "M"
},
...
]
I am not using anything like lodash. How can I improve this performance?
const data = [
{
"fName": "Jon",
"lName": "Doe",
"age": "30",
"shirtSize": "M"
},
{
"fName": "Jane",
"lName": "Foe",
"age": "25",
"shirtSize": "M"
}
];
const keyList = ["age", "shirtSize"];
const filteredDataset = data.map((elem) => {
let tempHolder = {};
for (let key of keyList) {
tempHolder[key] = elem[key];
}
return tempHolder;
});
return filteredDataset;
var results = [];
for(var person of data){
var obj = {};
for(var key of keyList){
obj[key] = person[key];
}
results.push(obj);
}
The first loop iterates through data, and the inner loop iterates through keyList and adds those attributes to the temporary object, which is then pushed to the results array.
EDIT: Your code is basically the same, with yours just using map to iterate through instead of a for...of loop.
You can express the same algorithm more declaratively:
const select = (props) => (objs) =>
objs .map (o => Object .fromEntries (props .map (p => [p, o[p]])))
const items = [{fName: "Jon", lName: "Doe", age: "30", shirtSize: "M"}, {fName: "Jane", lName: "Foe", age: "25", shirtSize: "M"}]
console .log (select (["age", "shirtSize"]) (items))

How to compare elements in array objects using javascript

I am new to javascript usage.
I have a requirement to compare the field from two different array objects which are having list as below.
Array - A
[
{
"id": "xyz",
"number": "123",
"place": "Here",
"phone": "9090909090"
},
{
"id": "abc",
"number": "456",
"place": "There",
"phone": "9191919191"
},
]
Array - B
[
{
"element1" : "ert",
"id1":"iii",
"element2":"erws",
"element3":"234"
}
,
{
"element1" : "uio",
"id1":"xyz",
"element2":"puy",
"element3":"090"
}
]
The scenario is to compare for each 'id' in the list of array A, with the list of Array B to field 'id1'
Example -
I need to check from Array A -> 'id:xyz' matches the array B object field 'id1'.
Array A - id: xyz should match with id1: xyz in Array B
If the match occurs I need to pull out complete object from the array list A.
here id:xyz matches with id1:xyz
then pull out as below
[
{
"id": "xyz",
"number": "123",
"place": "Here",
"phone": "9090909090"
}
]
Please help me with the suggestions to make this work using javascript.
const A = [
{
"id": "xyz",
"number": "123",
"place": "Here",
"phone": "9090909090"
},
{
"id": "abc",
"number": "456",
"place": "There",
"phone": "9191919191"
},
];
const B = [
{
"element1" : "ert",
"id1":"iii",
"element2":"erws",
"element3":"234"
},
{
"element1" : "uio",
"id1":"xyz",
"element2":"puy",
"element3":"090"
}
];
const C = A.filter(a => B.some(b => b.id1 === a.id));
console.log(C);
// the usage of `const` here means that arrA cannot be re-declared
// this is good for data that should not be changed
const arrA = [{
"id": "xyz",
"number": "123",
"place": "Here",
"phone": "9090909090"
},
{
"id": "abc",
"number": "456",
"place": "There",
"phone": "9191919191"
},
];
const arrB = [{
"element1": "ert",
"id1": "iii",
"element2": "erws",
"element3": "234"
},
{
"element1": "uio",
"id1": "xyz",
"element2": "puy",
"element3": "090"
}
];
// slow method for long lists, fine for short lists or if there are duplicates
// compares each entry in array A to each entry in array B
const out1 = arrA.filter(x => arrB.some(y => x.id === y.id1));
console.log("Example 1: \n", out1);
// faster for long lists
// creates a set of unique values for array B's id1 parameter, ignores duplicates
// then checks that set for each entry in array A
const setB = arrB.reduce((a, b) => {
a.add(b.id1);
return a;
}, new Set());
const out2 = arrA.filter(x => setB.has(x.id));
console.log("Example 2: \n", out2)
.as-console-wrapper { min-height: 100% } /* this is just to make the stack overflow output prettier */

Change structure of a JavaScript object

I have this object structure:
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"supplier_id": 1,
"supplier_name": [
"Supplier1"
],
"supplier_code": "SUP001",
"count": "21"
}
}
I'd like to change it so it appears like this:
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"suppliers":[
{
"supplier_id": 1,
"supplier_name": [
"Supplier1"
]
}
],
"supplier_code": "SUP001",
"count": "21"
}
}
I tried this hoping it would work:
const group = accumulator[item.id];
group.suppliers = [];
group.suppliers = group.suppliers.push(item.supplier_name, item.supplier_id, item.supplier_code);
return accumulator;
Unfortunately that just seems to give me a count of the objects pushed into suppliers, suppliers isn't an array and supplier_id, supplier_name and supplier_code are still visible outside of suppliers:
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"supplier_id": 1,
"supplier_name": [
"Supplier1"
],
"supplier_code": "SUP001",
"count": "21",
"suppliers: 3
}
}
How do I change it to the format I want?
You could use es6 Destructuring assignment, Object.values es2017 (or Object.keys instead).
If you assume that users contains more then one user you could use reduce.
In the example below original object won't be mutated.
Hope it helps
const original = {
"users": {
"1": {
"id": 1,
"name": "John",
"email": "john#doe.com",
"supplier_id": 1,
"supplier_name": [
"Supplier1"
],
"supplier_code": "SUP001",
"count": "21"
}
}
};
const { users } = original;
const reshaped = Object.values(users).reduce((acc, { id, supplier_id, supplier_name, ...rest }) => {
acc[id] = {
...rest,
suppliers: [{
supplier_id,
supplier_name: [supplier_name]
}]
};
return acc;
}, {});
console.log(reshaped);
You need to use an object to push into the suppliers array. Also, delete the old keys which are not needed.
Edit - You can directly create an array of 1 object. Thanks #Adam
const group = accumulator[item.id];
group.suppliers = [{
supplier_id: item.supplier_id,
supplier_name: item.supplier_name,
supplier_code: item.supplier_code
}];
delete group.supplier_id;
delete group.supplier_name;
delete group.supplier_code;
return accumulator;
Here's a quick and modern solution:
const parseUsers = (users) => {
let parsedUsers = {};
for (key in users) {
const user = users[key];
// destructuring (or extracting) the relevant keys from the . user object, keeping everything else under 'rest'
const { supplier_id, supplier_name, ...rest } = user;
parsedUsers[key] = {
...rest, // spreading back our rest params
suppliers: [ // creating a new array and populating it with the keys which we previously extracted (along with their corresponding values)
supplier_id,
supplier_name
]
}
}
return parsedUsers;
}
usage: parseUsers(json.users)

How to merge two javascript arrays based on property values?

I have two arrays
array1 = [{"id":1,"name":"Michale Sharma","gender":"Male","age":25,"salary":10000},{"id":2,"name":"Sunil Das","gender":"Male","age":24,"salary":5000},{"id":3,"name":"Robin Pandey","gender":"Male","age":35,"salary":45000},{"id":4,"name":"Mona Singh","gender":"Female","age":27,"salary":12000}]
array2 = [{"Deptid":1,"Deptname":"IT"},{"Deptid":12,"Deptname":"HR"},{"Deptid":3,"Deptname":"HW"}]
Output:
{ "0": { "id": 1, "name": "Michale Sharma", "gender": "Male", "age": 25, "salary": 10000, "Deptid": 1, "Deptname": "IT" }, "1": { "id": 2, "name": "Sunil Das", "gender": "Male", "age": 24, "salary": 5000}, "2": { "id": 3, "name": "Robin Pandey", "gender": "Male", "age": 35, "salary": 45000, "Deptid": 3, "Deptname": "HW" }, "3": { "id": 4, "name": "Mona Singh", "gender": "Female", "age": 27, "salary": 12000 }, "4" :{ "Deptid": 12, "Deptname": "HR" } }
I want to merge them based on the property values e.g id of array1 and Deptid of array2
Which means if id value = 1 and Deptid value = 1, then merge the records, if not then keep the values from one array and the other will be null. In another words, kind of the functionality of FULL OUTER JOIN. Because the array data cannot be a sequential one and may not be of the same length.
I have tried with Jquery.extend as under
$.extend(true, array1,array2)
It does not accept any property but merges the arrays.
I have also seen this but it does not help.
Looks like you need to have a custom logic. Here is sample using lodash library:
var array1 = [{"id":1,"name":"Michale Sharma","gender":"Male","age":25,"salary":10000},{"id":2,"name":"Sunil Das","gender":"Male","age":24,"salary":5000},{"id":3,"name":"Robin Pandey","gender":"Male","age":35,"salary":45000},{"id":4,"name":"Mona Singh","gender":"Female","age":27,"salary":12000}]
var array2 = [{"Deptid":1,"Deptname":"IT"},{"Deptid":12,"Deptname":"HR"},{"Deptid":3,"Deptname":"HW"}]
var defaults = {
Deptid: null,
DeptName: null
};
_.each(array1, function (obj) {
var dept = _.find(array2, { Deptid: obj.id });
_.defaults(obj, dept, defaults);
});
Using LoDash, roughly something like this:
_.reduce(array1, function(res, item1) {
var found = _.find(array2, function(item2) {
return item1.id === item2.Deptid;
});
if (found) res.push(_.merge({}, item1, found));
return res;
}, []);
EDIT: Sorry, I forgot about merging empty props.
It would be something like this (unoptimized):
function join(array1, array2) {
var keys = _.keys(array2[0]);
var vals = _.map(keys, function() { return '' });
return _.map(array1, function(item1) {
var found = _.find(array2, function(item2) {
return item1.id === item2.Deptid;
});
if (found)
return _.merge({}, item1, found);
return _.merge({}, item1, _.zipObject(keys, vals));
}, []);
}

Categories