'Find common objects in multiple arrays by object ID
I've searched SO for a way to do this but most questions only support two arrays (I need a solution for multiple arrays).
I don't want to compare exact objects, I want to compare objects by their ID, as their other parameters may differ.
So here's the example data:
data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'andrew'}, etc.]
data2 = [{'id':'22','name':'mary'},{'id':'85','name':'bill'}, etc.]
data3 = [{'id':'20','name':'steve'},{'id':'22','name':'john'}, etc.]
...
I'd like to return all objects whose ID appears in all arrays, and I don't mind which of the set of matched objects is returned.
So, from the data above, I'd expect to return any one of the following:
{'id':'22','name':'andrew'}
{'id':'22','name':'mary'}
{'id':'22','name':'john'}
Thanks
Solution 1:[1]
First, you really need an array of arrays - using a numeric suffix is not extensible:
let data = [ data1, data2, ... ];
Since you've confirmed that the IDs are unique within each sub array, you can simplify the problem by merging the arrays, and then finding out which elements occur n
times, where n
is the original number of sub arrays:
let flattened = data.reduce((a, b) => a.concat(b), []);
let counts = flattened.reduce(
(map, { id }) => map.set(id, (map.get(id) || 0) + 1), new Map()
);
and then you can pick out those objects that did appear n
times, in this simple version they'll all come from the first sub array:
let found = data[0].filter(({ id }) => counts.get(id) === data.length);
Picking an arbitrary (unique) match from each sub array would be somewhat difficult, although picking just one row of data
and picking the items from that would be relatively easy. Either would satisfy the constraint from the question.
Solution 2:[2]
If you want the unique object by Name
data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'mary'}]
data2 = [{'id':'26','name':'mary'},{'id':'85','name':'bill'}]
data3 = [{'id':'29','name':'sophie'},{'id':'22','name':'john'}]
flattened = [ ...data1, ...data2, ...data3 ];
counts = flattened.reduce(
(map, { name }) => map.set(name, (map.get(name) || 0) + 1), new Map()
);
names = []
found = flattened.filter(({ name }) => {
if ((counts.get(name) > 1) && (!names.includes(name))) {
names.push(name);
return true
}
return false
});
Solution 3:[3]
its too many loops but , if u can find the common id which is present in all the arrays then it would make your finding easier i think .you can have one array value as reference to find the common id
var global = [];
for(var i = 0;i<data1.length;i++){
var presence = true;
for(var j=0;j<arrays.length;j++){
var temp = arrays[j].find(function(value){
return data1[i].id == value.id;
});
if(!temp){
presence = false;
break;
}
}
if(presence){
global.push(data1[i].id)
}
}
console.log(global);
var data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'andrew'}];
var data2 = [{'id':'22','name':'mary'},{'id':'85','name':'bill'}];
var data3 = [{'id':'20','name':'steve'},{'id':'22','name':'john'}];
var arrays = [data1, data2, data3];
var global = [];
for(var i = 0;i<data1.length;i++){
var presence = true;
for(var j=0;j<arrays.length;j++){
var temp = arrays[j].find(function(value){
return data1[i].id == value.id;
});
if(!temp){
presence = false;
break;
}
}
if(presence){
global.push(data1[i].id)
}
}
console.log(global);
Solution 4:[4]
There's mention you you need n arrays, but also, given that you can:
put all the arrays into an array called data
you can:
- combine your arrays
- get a list of duplicated IDs (via sort by ID)
- make that list unique (unique list of IDs)
- find entries in the combined list that match the unique IDs
- where the count of those items match the original number of arrays
Sample code:
// Original data
var data1 = [{'id':'13','name':'sophie'},{'id':'22','name':'andrew'}]
var data2 = [{'id':'22','name':'mary'},{'id':'85','name':'bill'}]
var data3 = [{'id':'13','name':'steve'},{'id':'22','name':'john'}]
var arraycount = 3;
// Combine data into a single array
// This might be done by .pushing to an array of arrays and then using .length
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?v=control
var data = [].concat(data1).concat(data2).concat(data3);
//console.log(data)
// Sort array by ID
// http://stackoverflow.com/questions/840781/easiest-way-to-find-duplicate-values-in-a-javascript-array
var sorted_arr = data.slice().sort(function(a, b) {
return a.id - b.id;
});
//console.log(sorted_arr)
// Find duplicate IDs
var duplicate_arr = [];
for (var i = 0; i < data.length - 1; i++) {
if (sorted_arr[i + 1].id == sorted_arr[i].id) {
duplicate_arr.push(sorted_arr[i].id);
}
}
// Find unique IDs
// http://stackoverflow.com/questions/1960473/unique-values-in-an-array
var unique = duplicate_arr.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
//console.log(unique);
// Get values back from data
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter?v=control
var matches = [];
for (var i = 0; i < unique.length; ++i) {
var id = unique[i];
matches.push(data.filter(function(e) {
return e.id == id;
}))
}
//console.log(matches)
// for data set this will be 13 and 22
// Where they match all the arrays
var result = matches.filter(function(value, index, self) {
return value.length == arraycount;
})
//console.log("Result:")
console.log(result)
Note: There's very likely to be more efficient methods.. I've left this in the hope part of it might help someone
Solution 5:[5]
var arr1 = ["558", "s1", "10"];
var arr2 = ["55", "s1", "103"];
var arr3 = ["55", "s1", "104"];
var arr = [arr1, arr2, arr3];
console.log(arr.reduce((p, c) => p.filter(e => c.includes(e))));
// output ["s1"]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Vijay Chouhan |
Solution 3 | subbu |
Solution 4 | |
Solution 5 | Micha? RĂ³?ycki |