3

When using indexOf, I can just locate the position of the first appearance:

for example:

a=[1,2,4,2];
b=a.indexOf(2);
alert(b) //returns 1

Is there any alternative function to indexOf to find the both position or am I missing something? I am looking for the shortcut. Of course, I can always go for writing a simple look to find it.

Jack_of_All_Trades
  • 10,942
  • 18
  • 58
  • 88

4 Answers4

5

indexOf takes a second argument (the starting index)

So a.indexOf(2,2) would give you 3

To generalize, if x = a.indexOf(2), then the next instance is a.indexOf(2, x+1)

PSL
  • 123,204
  • 21
  • 253
  • 243
SheetJS
  • 22,470
  • 12
  • 65
  • 75
3

With one loop :

function indexesOf(arr, target) {
    let index = [];
    // For each element, index pushed in index[]
    arr.forEach((el, i) => {
        if (el === target) index.push(i)
    });
    return index;
}
alert(indexesOf([1, 2, 4, 2], 2));  // -> 1, 3

With two loops :

function indexesOf(arr, target) {
  // Map matching elements to their index, and others to null.
  return arr.map(function (el, i) { return (el === target) ? i : null; })
            // Throw out the nulls.
            .filter(function (x) { return x !== null; });
}

alert(indexesOf([1, 2, 4, 2], 2));  // -> 1, 3
Malron
  • 13
  • 6
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • 2
    Note: what this won't do is find the indexes of `NaN` in an array, if that is what you require from the function, so you would need an alternative comparison method rather than `===` – Xotic750 Jul 11 '13 at 18:19
  • 1
    @Xotic750, It's exactly like `Array.prototype.indexOf` in that manner. Section [15.4.4.14 / 9 b ii](http://es5.github.io/#x15.4.4.14) says that `indexOf` uses the *strict equality algorithm* which uses the usual semantics for NaN equality. – Mike Samuel Jul 11 '13 at 19:38
  • Yes, I was just making a note in case someone tried to use it for such and then wondered why it didn't work. :) – Xotic750 Jul 11 '13 at 20:41
1

As you are using a recent ECMAScript 5 method then you may want to consider using Array.map and Array.filter along with a new Harmony proposed method Object.is

Javascript

var func = {}.is,
    is;

if (typeof func === "function") {
    is = func;
} else {
    is = function is(x, y) {
        if (x === y) {
            if (x === 0) {
                return 1 / x === 1 / y;
            }

            return true;
        }

        var x1 = x,
            y1 = y;

        return x !== x1 && y !== y1;
    };
}

function indexesOf(array, value) {
    if (!Array.isArray(array)) {
        throw new TypeError("First attribute must be an array.");
    }

    return array.map(function (element, index) {
        if (is(value, element)) {
            return index;
        }
    }).filter(function (element) {
        return typeof element === "number";
    });
}

var test = [1, 2, 4, 2];

console.log(indexesOf(test, 2));

Output

[1, 3] 

On jsfiddle

Update: I have been castigated in the past for using loops when people have the strong belief "but this is exactly what these new methods are designed for". So, I am going to present alternative single loop solutions too.

ECMAScript 5 Array.reduce

Javascript

function indexesOf(array, value) {
    if (!Array.isArray(array)) {
        throw new TypeError("First attribute must be an array.");
    }

    return array.reduce(function (previous, current, index) {
        if (is(value, current)) {
            previous.push(index);
        }

        return previous;
    }, []);
}

On jsfiddle

ECMAScript 5 Array.forEach

Javascript

function indexesOf(array, value) {
    if (!Array.isArray(array)) {
        throw new TypeError("First attribute must be an array.");
    }

    var indexes = [];

    array.forEach(function (element, index) {
        if (is(value, element)) {
            indexes.push(index);
        }
    });

    return indexes.
}

On jsfiddle

ECMAScript 5 Array.indexOf

Note: this method is unable to find the indexes of NaN

Could also use Array.lastIndexOf and work in reverse

Javascript

function indexesOf(array, value) {
    if (!Array.isArray(array)) {
        throw new TypeError("First attribute must be an array.");
    }

    var index = array.indexOf(value),
        indexes = [];

    while (index !== -1) {
        indexes.push(index);
        index = array.indexOf(value, index + 1);
    }

    return indexes;
}

On jsfiddle

standard for

Javascript

function indexesOf(array, value) {
    if ({}.toString.call(array) !== "[object Array]") {
        throw new TypeError("First attribute must be an array.");
    }

    var indexes = [],
        length,
        index;

    for (index = 0, length = array.length; index < length; index += 1) {
        if (array.hasOwnProperty(index) && is(value, array[index])) {
            indexes.push(index);
        }
    }

    return indexes;
}

On jsfiddle

Standard while

Javascript

function indexesOf(array, value) {
    if ({}.toString.call(array) !== "[object Array]") {
        throw new TypeError("First attribute must be an array.");
    }

    var length = array.length,
        indexes = []
        index = 0;

    while (index < length) {
        if (array.hasOwnProperty(index) && is(value, array[index])) {
            indexes.push(index);
        }

        index += 1;
    }

    return indexes;
}

On jsfiddle

Standard for...in

Note: This is NOT recommended, but should be fine.

Why is using “for…in” with array iteration such a bad idea?

Javascript

function indexesOf(array, value) {
    if ({}.toString.call(array) !== "[object Array]") {
        throw new TypeError("First attribute must be an array.");
    }

    var indexes = [],
        prop;

    for (prop in array) {
        if (array.hasOwnProperty(prop) && is(+prop, prop >>> 0) && is(value, array[prop])) {
            indexes.push(+prop);
        }
    }

    return indexes;
}

On jsfiddle

Note: All of the solutions here handle both dense and sparse arrays.

And finally a jsperf comparing all of these solutions.

Community
  • 1
  • 1
Xotic750
  • 22,914
  • 8
  • 57
  • 79
0

lastIndexOf() gives the index of last occurence.

But if want an array of indices containing all the occurences of a particular element(2 in your case), you have to write a loop.

Praveen S
  • 104
  • 11