1

I'm trying to get the row and column index of an element from a 2D array using map function.

Here's my code -

function getIndex() {
  var values = [['a', 'f', 'k', 'p', 'u'], ['b', 'g', 'l', 'q', 'v'], ['c', 'h', 'm', 'r', 'w'], ['d', 'i', 'n', 's', 'x'], ['e', 'j', 'o', 't', 'y']];
  var output = values.map(function (row, rowIndex) {
    return row.map(function (col, colIndex) {
      if (col == 's') {
        return values[rowIndex][colIndex];
      }
    })
  });
  console.log(output);
}
getIndex();

And this is the output that I get when I run it at my end -

[[null, null, null, null, null], [null, null, null, null, null], [null, null, null, null, null], [null, null, null, s, null], [null, null, null, null, null]]

I don't intend to use a for loop as that would not be optimal for the data set that I'm working on. Need to use either map, reduce or filter functions in JavaScript Arrays. Please help!

Note: I only need the row and column Index for both and not the actual value.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320

3 Answers3

2

When iterating over rows, use .findIndex so that if the callback returns a truthy value, you can use the index outside. When iterating over columns, use indexOf to check to see if the value you're looking for exists in the array - if it does, assign it to an outside variable, and return true to the findIndex:

const rows = [
  ['a', 'f', 'k', 'p', 'u'],
  ['b', 'g', 'l', 'q', 'v'],
  ['c', 'h', 'm', 'r', 'w'],
  ['d', 'i', 'n', 's', 'x'],
  ['e', 'j', 'o', 't', 'y']
];
let colIndex = -1;
const rowIndex = rows.findIndex((row) => {
  const foundColIndex = row.indexOf('s');
  if (foundColIndex !== -1) {
    colIndex = foundColIndex;
    return true;
  }
});
console.log(rowIndex, colIndex);

If nothing is found, both values will be -1.

If your environment is so ancient that it doesn't support ES6 functions, then you could polyfill it first:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex#Polyfill

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • The IDE that I'm using doesn't support `findIndex` :( –  Jan 09 '20 at 05:16
  • 2
    Probably time to get a new IDE, if it doesn't even support ES2015. That was 5 years ago, which is an eternity in web development time... Best to write in the latest and greatest version of the language, and transpile down to ES5 for obsolete browsers for development (but not before!) – CertainPerformance Jan 09 '20 at 05:20
1

You can try this

const rows = [
    ['a', 'f', 'k', 'p', 'u'],
    ['b', 'g', 'l', 'q', 'v'],
    ['c', 'h', 'm', 'r', 'w'],
    ['d', 'i', 'n', 's', 'x'],
    ['e', 'j', 'o', 't', 'y']
];
let col;
rows.map((currElement, index) => {
    col = currElement.indexOf("s");
    if (col > -1) {
        console.log(index, col)
    }
});
Dev Ananth
  • 447
  • 1
  • 3
  • 10
  • As shared in my OP, trying to avoid `for` loops to avoid script timeout. While this is just a dummy data set, I intend to use the code on a much larger dataset - 100000+ cells. –  Jan 09 '20 at 05:24
0

A for loop can be efficient if you need only one match out of a search. Once a match is found just use break to stop any further processing. Using map() or .filter() forces the process to go through the whole array. reduce() could be stopped but it's not simple.

To index the rows and columns of a 2D array, use .entries() which can take an array and return an array of [key, value] pairs. The key will be the index number of the value. Details are commented in demo below.

const table = [
  ['a', 'f', 'k', 'p', 'u'],
  ['b', 'g', 'l', 'q', 'v'],
  ['c', 'h', 'm', 'r', 'w'],
  ['d', 'i', 'n', 's', 'x'],
  ['e', 'j', 'o', 't', 'y']
];

// Pass in 2D array and value to find
const getRC = (twoDArray, value) => {

  // Make a copy of given array
  let clone = [...twoDArray];
  // Declare empty array
  let rc = [];

  /* 
  clone.entries() will have [key, value] pairs
  key is an index number and value will be an array
  ex. [[0, ['a', 'f', 'k', 'p', 'u']], [1, ['b', 'g', 'l', 'q', 'v']], [2, [...]], [3, [...]], ...] 
  */
  for (let [rowIdx, columns] of clone.entries()) {

    /*
    columns.entries() is the same as above applied to the sub-arrays
    ex. [[0, 'a'], [1, 'f'], [2, 'k'], ...]
    */
    for (let [colIdx, column] of columns.entries()) {

      // if a match is found...
      if (column === value) {

        // add the row and column index number of the match into rc array
        rc.push(rowIdx, colIdx);

        // then break the loop
        break;
      }
    }
  }
  return rc;
}

// Not required just a utility function to prettify log
const log = data => console.log(JSON.stringify(data));

log(getRC(table, 'j'));

log(getRC(table, 'g'));

log(getRC(table, 'z'));
zer00ne
  • 41,936
  • 6
  • 41
  • 68