2

I'm looking for a way to make comparisons between arrays in arrays.

let small = [[1, 3], [2, 2], [2, 3], [3, 0]];

let large = [[1, 0], [1, 1], [2, 0], [2, 2], [2, 5], [3, 0], [3, 2]];

For example, I would like to be able to find out how many of the arrays in small are found in large. Some function that, given the arrays above as arguments, would return 2, since [2, 2] and [3, 0] from small are found in large.

How would you go about doing that?

3
  • 3
    You can turn large into a Set or Object with large[0] and large[1] as keys seperated with - and then do lookups using small's values Commented Nov 1, 2018 at 23:57
  • 1
    Have you made any attempt at solving it? Commented Nov 1, 2018 at 23:57
  • May be you could convert every subarray to a string with join function and then compare only strings. Commented Nov 1, 2018 at 23:59

5 Answers 5

2

You can convert one of the arrays into a Set of hashes, and than filter the 2nd array using the set:

const small = [[1, 3], [2, 2], [2, 3], [3, 0]];

const large = [[1, 0], [1, 1], [2, 0], [2, 2], [2, 5], [3, 0], [3, 2]];

const containsCount = (arr1, arr2, hashFn) => {
  const arr1Hash = new Set(arr1.map(hashFn));
  
  return arr2.filter(s => arr1Hash.has(hashFn(s))).length;
}

const result = containsCount(small, large, ([a, b]) => `${a}-${b}`); 

console.log(result);

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

1 Comment

Took me a while to figure out what was going on here, but I like the solution. Learning a ton. Thanks!
1

You can try something like:

let small = [[1, 3], [2, 2], [2, 3], [3, 0]];
let large = [[1, 0], [1, 1], [2, 0], [2, 2], [2, 5], [3, 0], [3, 2]];

let z = zeta(small, large);
console.log(z);

function zeta(a, b) {
  let join = m => m.join();
  let x = a.map(join);
  let y = b.map(join);
  
  return x.reduce((n, m) => (y.indexOf(m)>0) ? ++n : n, 0);
}

I hope this helps!

3 Comments

Turning the arrays into strings makes sense, but I'm struggling to make sense of the return statement.
Array.prototype.reduce() is a versatile method. I initialize a counter n to 0, looping over x[] and testing if element m of x[] is in y[]. If so, ++ n else return n unmodified. n is implicitly returned by this use of arrow functions thus n's value is maintained in subsequent calls to the anonymous arrow function. Finally, n is returned by reduce() then returned by zeta().
Thank you for the clarification. Helps a lot!
1

Use every and some to compare the arrays with each other.

If you want to get an array containing the subarrays that match, use filter:

let result = small.filter(arr => 
  large.some(otherArr =>
    otherArr.length === arr.length && otherArr.every((item, i) => item === arr[i])
  )
);

Which filters the subarray from small that some subarray from large has the same length and the same elements/items.

Demo:

let small = [[1, 3], [2, 2], [2, 3], [3, 0]];

let large = [[1, 0], [1, 1], [2, 0], [2, 2], [2, 5], [3, 0], [3, 2]];

let result = small.filter(arr => 
  large.some(otherArr =>
    otherArr.length === arr.length && otherArr.every((item, i) => item === arr[i])
  )
);

console.log(result);

And if you want just a count, then use reduce instead of filter to count the mathched items (this makes use of the fact that the numeric value of true is 1 and that of false is 0):

let count = small.reduce((counter, arr) => 
  counter + large.some(otherArr =>
    otherArr.length === arr.length && otherArr.every((item, i) => item === arr[i])
  )
, 0);

Demo:

let small = [[1, 3], [2, 2], [2, 3], [3, 0]];

let large = [[1, 0], [1, 1], [2, 0], [2, 2], [2, 5], [3, 0], [3, 2]];

let count = small.reduce((counter, arr) =>
  counter + large.some(otherArr =>
    otherArr.length === arr.length && otherArr.every((item, i) => item === arr[i])
  )
, 0);

console.log(count);

Note: If the subarrays contain only numbers, the code could be simplified to use Array#toString instead of every and length comparaison:

let result = small.filter(arr => large.some(otherArr => "" + otherArr === "" + arr));

Which casts both arrays into strings and compares the two strings instead. This can be used with the reduce as well.

Comments

0

Create two nesting map() function oute for small and inner for large then use JSON.stringify()

let small = [[1, 3], [2, 2], [2, 3], [3, 0]];
let large = [[1, 0], [1, 1], [2, 0], [2, 2], [2, 5], [3, 0], [3, 2]];
var same=[];
    small.map(function(element){
        large.map(function(element2){
            if(JSON.stringify(element)==JSON.stringify(element2)){
        same.push(element);
  }
 });
});
console.log(same);

Comments

0

let small = [[1, 3], [2, 2], [2, 3], [3, 0]];

let large = [[1, 0], [1, 1], [2, 0], [2, 2], [2, 5], [3, 0], [3, 2]];


let largeArrayStringForm = large.map(item => item.toString())
let matchingItems = small.filter(item => largeArrayStringForm.includes(item.toString()))

console.log(`matchCount: ${matchingItems.length}`)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.