Zenoo
Zenoo

Reputation: 12880

JS Last index of a non-null element in an array

I have an array with defined and null values inside, like so :

var arr = [
  {...},
  null,
  null,
  {...},
  null
];

Is there any way for me to get the index of the last non-null element from this array? And I mean without having to loop through it entirely.

Upvotes: 8

Views: 8154

Answers (5)

iROOT
iROOT

Reputation: 1

You can use the map function to iterate through the array, check the condition and return the index, then take the maximum index:

Math.max.apply(null, arr.map(function (v, i) { return v !== null && i; });

or

Math.max(...arr.map((v, i) => v !== null && i));

Upvotes: 0

berniecc
berniecc

Reputation: 411

Try this:

array.length - array.slice(0).reverse().findIndex(function (el) { return el }) - 1;

Upvotes: 0

Milesman34
Milesman34

Reputation: 197

const reverse = arr => {
    let cpy = [...arr];
    cpy.reverse();
    return cpy;
};

const nonNullIndex = arr => {
    let res = arr.length - 1 - reverse(arr).findIndex(e => e !== null)

    return res === arr.length ? -1 : res;
};

This should work. The reverse function returns an array, as Array.prototype.reverse reverses it in-place, not returning anything.

The nonNullIndex function returns the last index where it isn't null. Since it reverses the array, you must subtract the index found from the length of the array. The subtraction of one is used so that it returns the right value (since arrays are indexed at 0).

If the result is equal to the length (meaning that findIndex returned -1), it returns -1, meaning there are no null values in the array. Otherwise, it returns the result.

Upvotes: 0

PRAISER
PRAISER

Reputation: 803

Filter the non-null get the value of last one, if you need the index get the index from the value. But requires the values to be unique.

// Last non-null value
const lastNonNull = arr.filter(x => x).pop();
// Index of last non-null
const indexOfLastNonNull = arr.indexOf(lastNonNull);

--Edit(1)

You may want to use reduce method of arrays, but before run reverse to make sure the sequence is from last to first. reduce works pretty fine, the first initial value is null then we check for result which is the first initial value so we pass on cur which is the first element of array, if it is truthy we return idx which is the index of array, if not we return null which will become the result in the next loop.

arr.reduce((result, cur, idx) => (result ? result : (cur ? idx : null)), null)

--Edit(2)

Or you may reverse the array and run indexOf like this:

arr.indexOf(null);

For reversing once you run arr.reverse() it'll reverse the content of array. No need to return anything.

Upvotes: 4

Nina Scholz
Nina Scholz

Reputation: 386560

You could use a while loop and iterate from the end.

var array = [{ foo: 0 }, null, null, { bar: 42 }, null],
    index = array.length;
    
while (index-- && !array[index]);

console.log(index);
console.log(array[index]);

Upvotes: 9

Related Questions