Mostafiz
Mostafiz

Reputation: 7352

Get some set of array based on condition from two arrays of array in Javascript

I have two arrays of array in Javascript like

var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]];
var array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]];

I want to get the set of arrays from array1 which match the first element of each array of the array2

in my example case both array1 and array2 have array with first element as 10 11 and 12, so it should return

[[10, 2], [11, 4], [12, 30]];

is there any easy and efficient way using pure javscript or lodash, underscor framework or something like that. Without iterate over and match one by one of this two array ?

Upvotes: 4

Views: 1163

Answers (5)

Redu
Redu

Reputation: 26161

I would do this with a Map anf filter combo in ES6 as follows;

var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
    array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
         m = new Map(array2),
    array3 = array1.filter(a => m.has(a[0]));
console.log(array3);

If you need backwards compatibility other answers are pretty good.

Upvotes: 0

acontell
acontell

Reputation: 6922

You can use lodash _.intersectWith function in order to solve this problem in an inline.

_.intersectionWith(array1, array2, function(a, b) {
    return a[0] === b[0];
});

I don't know about performance cos I haven't had the chance to have a look at the source code of this function. Anyway, I like it for its simplicity. Here's the fiddle in case you want to check it out.

Upvotes: 3

Felix Kling
Felix Kling

Reputation: 816462

If you can make use of Set, then you can compute the a set of numbers to look for first and use .filter to only get the arrays whose first element is in that set:

var haystack = new Set(array2.map(x => x[0]));
var newArray = array1.filter(x => haystack.has(x[0]));

Of course you can also use the lodash or underscore versions of .map and .filter.


Alternatives to using Set would be:

  • Create an array of numbers instead and use indexOf to test existence. That will scale linearly with the number of elements:

    var haystack = array2.map(x => x[0]);
    var newArray = array1.filter(x => haystack.indexOf(x[0]) > -1);
    
  • Create an object with number -> true entries to test existence with in, hasOwnProperty or just object access:

    var haystack = array2.reduce((obj, x) => (obj[x[0]] = true, obj), {});
    var newArray = array1.filter(x => haystack[x[0]]);
    

Which one performs better depends on the number of elements you have and the environment the code is running in.

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386634

In ES6, you could use Set.

var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
    array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
    set = new Set(array2.map(a => a[0])),
    result = array1.filter(a => set.has(a[0]));

console.log(result);

Version with an object as hash table

var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
    array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
    result = array1.filter(function (a) {
        return this[a[0]];
    }, array2.reduce(function (r, a) { 
        r[a[0]] = true;
        return r;
    }, Object.create(null)));

console.log(result);

Upvotes: 4

Nenad Vracar
Nenad Vracar

Reputation: 122047

You can do this with filter() and find()

var array1 = [
  [10, 2],
  [11, 4],
  [12, 30],
  [13, 17],
  [14, 28]
];
var array2 = [
  [8, 13],
  [9, 19],
  [10, 6],
  [11, 7],
  [12, 1]
];

var result = array1.filter(function(ar) {
  return array2.find(function(e) {
    return e[0] == ar[0]
  })
})

console.log(result)

Upvotes: 1

Related Questions