1

Consider this array:

const arr = [
[1, 2, 3, 4, 3, 2, 4]
,[1, 0, 3, 4, 3, 2, 0]
,[undefined, 0, null, 4, 3, null, 0]
,[undefined, undefined, 5, 7, undefined, null, undefined]
];

My task is to trim each array. Valid values are integers (or floats, same thing). 0 is also considered valid. Trimming in this case means that the array needs to be cropped at the beginning and at the end.

In the examples above:

arr[0] does not need to remove any element
arr[1] does not need to remove any element
arr[2] needs to remove arr[2][0]
arr[3] needs to remove arr[3][0], arr[3][1] from the beginning and arr[3][4], arr[3][5], arr[3][6] at the end.

My approach has been the following:

First find out the first valid element in an array:

const foundStartIndex = arr[x].findIndex(el => el >= 0);    

This will help me to slice the array at the beginning.

But how do I find out from where to start removing at the end? There is a "lastIndexOf" but it looks it is not accepting a function the same way "findIndex" does. I could reverse the array, find the first valid element, and calculate where it should be places when it will be reversed back. But maybe there is a better way to do this? Please note that I need to know where, at what index, I need to begin to cut as the index will be used for other reasons.

oderfla
  • 1,695
  • 4
  • 24
  • 49
  • 4
    Does this answer your question? [Find last index of element inside array by certain condition](https://stackoverflow.com/questions/40929260/find-last-index-of-element-inside-array-by-certain-condition) – A_A Aug 15 '21 at 10:10

3 Answers3

1

Here is how I would do it.

I split the problem into 2: trimming the left part and trimming the right part.

To trim the left part, we just go through the array until we get a number, then slice the array from the beginning until that point.

To trim the right, it's just a mirror of the left trim.

Then for good measure, I added in a function that calls the 2 others for ease of use.

Note: Even though I checked for a number type, feel free to use a different check, like Number.isInteger() or element >= 0.

/**
 * @param {Array} arr
 */
function leftTrimArray(arr) {
  let i = 0
  let element = arr[i]
  while (typeof element !== 'number') {
    i++
    element = arr[i]
  }
  return arr.slice(i)
}

/**
 * @param {Array} arr
 */
function rightTrimArray(arr) {
  let i = arr.length - 1
  let element = arr[i]
  while (typeof element !== 'number') {
    i--
    element = arr[i]
  }
  return arr.slice(0, i + 1)
}

function trimArray(arr) {
  return rightTrimArray(leftTrimArray(arr))
}

const arrs = [
  [1, 2, 3, 4, 3, 2, 4],
  [1, 0, 3, 4, 3, 2, 0],
  [undefined, 0, null, 4, 3, null, 0],
  [undefined, undefined, 5, 7, undefined, null, undefined]
];

arrs.forEach(arr => {
  console.log(trimArray(arr));
})
Seblor
  • 6,947
  • 1
  • 25
  • 46
1

Following your approach, I recommend the following:

const reverseEndIndex = arr[x].reverse().findIndex(el => el >= 0);
const foundEndIndex = arr[x].length - 1 - reverseLastIndex;

The second code line translates the index in the reversed array to the index in the non-reversed array.

shuffler
  • 66
  • 5
1

It's not really clear from your question why you need to use the index "for other reasons", but if you need clean arrays containing only numbers you can map over them and then filter out everything that isn't null or a number.

const arr = [
  [1, 2, 3, 4, 3, 2, 4],
  [1, 0, 3, 4, 3, 2, 0, 'Bob'],
  [undefined, 0, null, 4, 3, null, 0, 0.2],
  [undefined, undefined, 5, 7, undefined, null, undefined]
];

const out = arr.map(n => n.filter(el => {
  return el !== null && !isNaN(el);
}));

console.log(out);
Andy
  • 61,948
  • 13
  • 68
  • 95