0

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

9
  • data.find(el => el.id === '22') Commented May 11, 2017 at 9:59
  • @Rayon what is data? If this is a solution can you please post it as a solution? Commented May 11, 2017 at 10:01
  • This would be a lot easier if data was an array of arrays, instead of a set of distinct variables Commented May 11, 2017 at 10:02
  • @Alnitak I can put all the arrays into an array called data, that's fine. But I still don't see what the number 22 has to do with my question :) Commented May 11, 2017 at 10:04
  • 1
    @Seano not me - that was someone else, who appears to have incorrectly assumed that you specifically want 22, and not which ever ID happens to be the one that's in every array. Commented May 11, 2017 at 10:09

5 Answers 5

2

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.

Sign up to request clarification or add additional context in comments.

13 Comments

I get Uncaught SyntaxError: Unexpected token } on the map line
this is ES6 code, that requires a modern browser. I did also just fix a typo on the .find line
Can you make it into a snippet?
@Alnitak ok the code runs now but it only gives me the first match. I need it to find all matches.
@Seano you wrote: "I'd expect to return any one of the following:"
|
1
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
});

Comments

0

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);

Comments

0

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

Comments

-1

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"]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.