0

There were a lot of questions asked about this topic, but I couldn't find the answer that addressed directly the issue I am having.

Here is one: Find common elements in 1 array using Javascript

The first difference is that I have a different type of array, its elements are objects with key-value pair, where key is the string and the value is an array of integers.

The second difference is that array is dynamic meaning that sometimes it may have zero elements and the other times it may have 3 object elements.

I am sharing the sample array below:

const array = [
  {"key1":[1,2,3]},
  {"key2":[2,3,4]},
  {"key3":[2,5,6]},
];

The third difference is that the order of elements matters so that final result should output the values of the first element that exist in all subsequent arrays.

The result should be:

const result = [2];

Since 2 is the only common integer of these three elements.

As mentioned array sometimes might have just 1 or 2 or no elements in it and those cases should be accounted.

Edit 1: as asked in the comments the values of array are unique

8
  • 1
    Are there multiple keys in each object or just one and why? Commented Jun 29, 2017 at 11:06
  • Is your sample array a good example of the kind of data you'll be using? Commented Jun 29, 2017 at 11:07
  • @Jonasw there is just one key in each object and the reason is that I am working with multiple dropdown lists where each option value corresponds to array value. When those dropdowns are selected I have to find intersection of values. Hope I could anwer your question. Commented Jun 29, 2017 at 11:08
  • @evolutionxbox yes it is good example read comment above to get better understanding of the situation Commented Jun 29, 2017 at 11:09
  • @bakhtiiar muzakparov well but dynamic keys are always a very very bad idea (difficult to use, difficult to optimize for the parser). So may change your structure to {id:"key1", values:[1,2,3]} Commented Jun 29, 2017 at 11:17

3 Answers 3

2

Since a value can appear in array only once, you can concat the arrays, count the number of appearances, and filter our those that are not equal to the length of the original array.

const findRecuring = (array) =>
  [...
    [].concat(...array.map((o) => Object.values(o)[0])) // combine to one array
   .reduce((m, v) => m.set(v, (m.get(v) || 0) + 1), new Map()) // count the appearance of all values in a map
 ] // convert the map to array of key/value pairs
 .filter(([, v]) => v === array.length) // filter those that don't appear enough times
 .map(([k]) => k); // extract just the keys

/** Test cases **/
console.log('Several:', findRecuring([
  {"key1":[6,1,2,3,8]},
  {"key2":[2,6,3,4,8]},
  {"key3":[2,5,6,8]},
]).join());

console.log('None: ', findRecuring([
  {"key1":[9,0,11]},
  {"key2":[2,6,3,4,8]},
  {"key3":[2,5,6,8]},
]).join());

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

1 Comment

Marking you as an answer for elegant and well-explained commented code.
0
const array = [
  {"key1":[1,2,3]},
  {"key2":[2,3,4]},
  {"key3":[2,5,6]},
];

You could iterate over and store how often a value appears in the array for each value:

var common=new Map();
array.forEach(function(obj){
 //var values=new Set(Object.values(obj)[0]);//make unique values out of array
 var values=Object.values(obj)[0];//no need for uniqueness as OP states that they are already unique..
 values.forEach(function(val){
     common.set(val,(common.get(val)||0)+1);
 });
});

Now youve got a map with all elements and their appearance in the main array. So now you can simply compare:

var result=[];
common.forEach(function(appearance,el){
  if(appearance===array.length){
   result.push(el);
  }
});

http://jsbin.com/xuyogahija/edit?console

Comments

0

You could get first the arrays in an array without using different keys and then lookup each element if it is in the other array.

let array = [{ key1: [1, 2, 3] }, { key2: [2, 3, 4] }, { key3: [2, 5, 6] }],
    result = array
        .map(o => o[Object.keys(o)[0]] || [])
        .reduce((a, b) => a.filter(c => b.includes(c)));
      
console.log(result);

5 Comments

Although your solution seems very elegant, it fails when there are no element at all. The error I get: "Uncaught TypeError: Reduce of empty array with no initial value..." . I wonder how your code could be altered to fix this.
Array.prototype.reduce() is meant to accept a second argument, which is the initial value. In that case, it would be .reduce((a, b) => a.filter(c => b.includes(c)), []);. This initial value is returned if the array (or variable) you process is null/empty.
@Ksyqo, then the result would always empty.
@BakhtiiarMuzakparov, you could add a default array if no property is given.
@Ksyqo I am getting empty array instead of [2] now

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.