Home > Net >  Find Index of 2D Array with multiple Elements
Find Index of 2D Array with multiple Elements

Time:04-19

I have 2 Arrays. How can I check if Array 2 is in Array 1 and how can I find the index of the first Array.

0: (2) ['pik13', 'karo10']
1: ['karo14']
2: ['karo11']
3: (2) ['karo6', 'pik10']
4: ['herz10']
5: (3) ['pik11', 'kreuz10', 'kreuz11']
0: (3) ['pik11', 'kreuz10', 'kreuz11']

These are the 2 Arrays. The expected output should be 5.

CodePudding user response:

If the order does not matter you can use the following:

const searchIn = [
  ["pik13", "karo10"],
  ["karo14"],
  ["karo11"],
  ["karo6", "pik10"],
  ["herz10"],
  ["pik11", "kreuz10", "kreuz11"],
];

const searchFor = ["pik11", "kreuz10", "kreuz11"];

/**
 * Check if the the elements in an array matches the elements in the Set
 * @param {Array} array
 * @param {Set} toBeFound
 * @returns
 */
function compareArray(array, toBeFound) {
  // early outs it the element is not an array or the length does not match
  if (!Array.isArray(array) || array.length !== toBeFound.size) return false;
  // finds match in O(n) due fast lookup in Set
  return array.every((item) => toBeFound.has(item));
}

/**
 * Search for array in array.
 * @param {Array} toBeSearched
 * @param {Array} toBeFound
 * @returns
 */
function searchForArray(toBeSearched, toBeFound) {
  // use a set to make the lookups faster => O(1)
  const elements = new Set(toBeFound);
  return toBeSearched.findIndex((array) => compareArray(array, elements));
}

console.log(searchForArray(searchIn, searchFor));
This uses a Set to speed up the lookup when comparing array values to O(1) in contrast to using includes() which will result in a worst case lookup runtime of O(n). By reason of this the worst case runtime for compareArray() is O(n) instead of O(n²). In most cases it will even be significantly faster as for instance in your example there is only one array which matches in length with the array we search for, so that we only compare the array values once. Overall in worst case the algorithm will take O(m * n) where m is the number of arrays to search and n is the number of elements in the array we are looking for.

This will not work if you search for nested arrays, but can made to work with some changes for deep comparisons.

CodePudding user response:

If the order DOES matter....

let arr =[['pik13', 'karo10'],['karo14'],['karo11'],['karo6', 'pik10'],['herz10'],['pik11', 'kreuz10','kreuz11'],];
let compare = ['pik11', 'kreuz10', 'kreuz11'];
let index = arr.findIndex(x => JSON.stringify(x)===JSON.stringify(compare)); 
// This could also for a bit more speed use String(x) === String(compare) as @Thomas notes in the below comments

console.log(index);

As pointed out in the comments, JSON.Stringify can be very slow, for small array's and non-intensive calculations it's probably fine, so here's a faster method for 1 for 1 comparing that doesn't convert the array to a string:

let arr =[['pik13', 'karo10'],['karo14'],['karo11'],['karo6', 'pik10'],['herz10'],['pik11', 'kreuz10', 'kreuz11']];
let compare = ['karo6', 'pik10'];
let index = arr.findIndex(x => x.length === compare.length && x.every((v,i)=> compare[i] === v));

console.log(index);

If the order DOESN'T matter...

let arr =[['pik13', 'karo10'],['karo14'],['karo11'],['karo6', 'pik10'],['herz10'],['pik11', 'kreuz10', 'kreuz11']];
let compare = ['kreuz10', 'kreuz11', 'pik11'];
let index = arr.findIndex(x => x.length === compare.length && x.every((i)=> compare.includes(i)));

console.log(index);

CodePudding user response:

You can use JSON.stringify for array equality and findIndex to get the result index.

const array2D = [['pik13', 'karo10'],['karo14'],['karo11'],['karo6', 'pik10'],['herz10'],['pik11', 'kreuz10', 'kreuz11']]

const subjectArray1D = ['pik13', 'karo10'];

const result = array2D.findIndex((array1D) => {
  return JSON.stringify(array1D) === JSON.stringify(subjectArray1D);
});

console.log(result);

  • Related