How to get index of all occurences of the same value in an Array?
Asked Answered
P

4

6

I am using a set of numerical values in an array where certain values are be repeated. I want to find the indices of ALL of the occurrences of a repeated value.

For example, I have the following code using indexOf():

var dataset = [2,2,4,2,6,4,7,8];
return dataset.indexOf(2);

But this only gives the index of the first occurrence of 2. (i.e. it returns the value 0.)

However, I want the indices for ALL the occurrences of 2 to be returned (i.e. 0,1,3). How can I do this? (I know I could use a for loop, but I'm wondering if there's a better way to do this having without iterating through the whole array. Basically, I'm trying to save the overhead of explicitly iterating through the whole array.)

Pugliese answered 26/6, 2013 at 5:42 Comment(0)
A
3

@Bagavatu: If you don't want a for loop you could try this fiddle -

var dataset = [2,2,4,2,6,4,7,8];
var results = [];

var ind

// the while loop stops when there are no more found
while( ( ind = dataset.indexOf( 2 ) ) != -1 ){
    results.push( ind + results.length )
    dataset.splice( ind, 1 )
}

return results;

NOTE: using a for loop would be MUCH quicker. See comments.

var dataset = [2,2,4,2,6,4,7,8];
var results = [];
for ( i=0; i < dataset.length; i++ ){
    if ( dataset[i] == 2 ){
        results.push( i );
    }
}

return results;
Alben answered 26/6, 2013 at 5:50 Comment(6)
Thanks for the answer, but this does still involve for loop iteration.Pugliese
@Bagavatu - Sorry, I missed that bit of your post. I think you cannot avoid iteration of some kind, as you need to check each value individually matches. Even if you use something like "filter" it still iterates over each entry, just not explicitly.Alben
Yeah, I was afraid that would be the case. If iteration must be involved, I would like to find a way to minimize the overhead of iteration. So something like filter. (My actual dataset is hundred of values long; I just shortened it for sake of brevity.)Pugliese
@Bagavatu - having benchmarked a for loop vs filter, it seem the for loop is quicker by a factor of 5 or 6. See this fiddle jsfiddle.net/Ballcheck/NmRs3/2Alben
Really? Never knew that. That's actually really good to know! But in your answer, if there a way you can do this without splice? I want to preserve the original array.Pugliese
@Bagavatu - I don't think so. Also, having benchmarked it I find that the while / splice method is MUCH worse for overhead. I would stick with the for loop as it is clean and optimised.Alben
O
3

You can use the filter() method of the Array object to handle nicely:

var dataset = [2, 2, 4, 2, 6, 4, 7, 8];
var indexs = [];
dataset.filter(function(elem, index, array){
    if(elem == 2) {
        indexs.push(index);
    }
});
alert(indexs);

And here is some more documentation on the filter() method, as well as a fallback for older browsers.

Oversweet answered 26/6, 2013 at 5:52 Comment(0)
J
1

Here you have an example: Try if yourself

var dataset = [2,2,4,2,6,4,7,8];

// We get the first indexOf number 2
var prev = dataset.indexOf(2);

// While we find indexes we keep searching
while (prev != -1) { 
    alert(prev);
    // we get the indexOf number 2 starting in the previous position + 1
    prev = dataset.indexOf(2, prev + 1);
}
Janeyjangle answered 26/6, 2013 at 5:48 Comment(2)
Could you please check your link? I ended up with a 404 error.Pugliese
Thanks, I can now see the JSFiddle. However, the while loop still has the effect of iteration. I never thought of it this way though, so thanks for that. +1.Pugliese
H
1

Looks like this functionality may not be possible out-of-the-box, but there is a 'plugin' available here by creating a Array.prototype.allIndexOf function.

It still iterates over the entire list (which is required), but it abstracts the logic a little bit.

Hospitaler answered 26/6, 2013 at 5:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.