16

I have an array which contains multiple same values

["test234", "test9495", "test234", "test93992", "test234"]

Here I want to get the index of every test234 in the array

For that I've tried Array.prototype.indexOf() method. But It only returns me 0 but I want it to return me [0, 2, 4].

How can I do that?

var array = ["test234", "test9495", "test234", "test93992", "test234"];
document.write(array.indexOf("test234"));
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • Possible duplicate of [How to find index of all occurrences of an element in array?](http://stackoverflow.com/questions/20798477/how-to-find-index-of-all-occurrences-of-an-element-in-array) – 4castle Apr 14 '16 at 20:51
  • This question is an exact duplicate, but I should mention that using a `for` loop is the most efficient solution to the task. – 4castle Apr 14 '16 at 21:26

7 Answers7

13

Just make it a for loop to check each array element.

var array = ["test234", "test9495", "test234", "test93992", "test234"];

for (i=0;i<array.length;i++) {
  if (array[i] == "test234") {
    document.write(i + "<br>");
  }
}
JoeL
  • 710
  • 4
  • 18
  • Can you make it as a prototype? –  Apr 14 '16 at 19:06
  • @MrZ If you mean adding it to `Array.prototype`, then the answer is yes, but that is bad practice and it has some unexpected effects. You would have to initialize every array using `new Array()` instead of `[]` for it to work. You're better off just making utility functions. – 4castle Apr 14 '16 at 20:43
  • 1
    You really should be using `===` instead of `==` for this to be a fool proof answer. [See this](http://stackoverflow.com/q/359494/5743988) – 4castle Apr 14 '16 at 21:32
  • @4castle I'll admit I don't have any experience with the triple = so while I read the link, it's still not perfectly clear to me what exact situations I should use it. – JoeL Apr 15 '16 at 14:11
  • @JoeL The === checks for type , so "1" and 1 and not the same when using === but when using == they are, because they are compared using a string or a numeric. So, == its more permissive because uses a loosely comparison. – Miguel Aug 24 '17 at 10:54
10

This kind of function doesn't exist built in, but it would be pretty easy to make it yourself. Thankfully, indexOf can also accept a starting index as the second parameter.

function indexOfAll(array, searchItem) {
  var i = array.indexOf(searchItem),
      indexes = [];
  while (i !== -1) {
    indexes.push(i);
    i = array.indexOf(searchItem, ++i);
  }
  return indexes;
}

var array = ["test234", "test9495", "test234", "test93992", "test234"];
document.write(JSON.stringify(indexOfAll(array, "test234")));
4castle
  • 32,613
  • 11
  • 69
  • 106
9

You can use reduce:

const indexesOf = (arr, item) => 
  arr.reduce(
    (acc, v, i) => (v === item && acc.push(i), acc),
  []);

So:

const array = ["test234", "test9495", "test234", "test93992", "test234"];
console.log(indexesOf(array, "test234")); // [0, 2, 4]

An alternative approach could be having an iterator:

function* finder(array, item) {
  let index = -1;
  while ((index = array.indexOf(item, index + 1)) > -1) {
    yield index;
  }
  return -1;
}

That's give you the flexibility to have the search in a lazy way, you can do it only when you need it:

let findTest234 = finder(array, "test234");

console.log(findTest234.next()) // {value: 0, done: false}
console.log(findTest234.next()) // {value: 2, done: false}
console.log(findTest234.next()) // {value: 4, done: false}    
console.log(findTest234.next()) // {value: -1, done: true}

Of course, you can always use it in loops (since it's an iterator):

let indexes = finder(array, "test234");

for (let index of indexes) {
   console.log(index);
}

And consume the iterator immediately to generate arrays:

let indexes = [...finder(array, "test234")];
console.log(indexes); // [0, 2, 4]

Hope it helps.

ZER0
  • 24,846
  • 5
  • 51
  • 54
  • Really like this code and reducer functions, could you add a note about what each variable represents, wondering exactly what to use for arr, item, acc, v, i. – Greggory Wiley Mar 23 '21 at 17:12
  • 1
    Thanks! If you're referring to `(acc, v, i)`, they're just the `accumulator`, the `value`, and the `index` as described in the [reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) documentation I linked. Or did you mean something else? – ZER0 Mar 25 '21 at 13:53
2

You can use the fromIndex of Array#indexOf.

fromIndex

The index to start the search at. If the index is greater than or equal to the array's length, -1 is returned, which means the array will not be searched. If the provided index value is a negative number, it is taken as the offset from the end of the array. Note: if the provided index is negative, the array is still searched from front to back. If the calculated index is less than 0, then the whole array will be searched. Default: 0 (entire array is searched).

~ is a bitwise not operator.

It is perfect for use with indexOf(), because indexOf returns if found the index 0 ... n and if not -1:

value  ~value   boolean
-1  =>   0  =>  false
 0  =>  -1  =>  true
 1  =>  -2  =>  true
 2  =>  -3  =>  true
 and so on 

var array = ["test234", "test9495", "test234", "test93992", "test234"],
    result = [],
    pos = array.indexOf('test234');

while (~pos) {
    result.push(pos);
    pos = array.indexOf('test234', pos + 1); // use old position incremented
} //                               ^^^^^^^

document.write('<pre> ' + JSON.stringify(result, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • I know exactly what it does and how it works. I'm just saying it's confusing in general. I prefer to code exactly what I mean instead of using strange operators. When it comes down to it, our code is almost identical. – 4castle Apr 14 '16 at 19:23
0

You may use indexOf with a for loop to get the index values of 0,2,4:

var array = ["test234", "test9495", "test234", "test93992", "test234"];
let newArr=[];
for (i=0;i<array.length;i++) {
  if (array[i].indexOf("test234") >=0 ) {
    newArr.push(i);
  }
}
document.write(newArr);
0

This is not the best answer, but I wanted to try a recursive method:

var indexOfFull = (array, key, startIndex = 0) => {
  let result = [];

  //Control errors
  if(!key) return result;
  if(!array) return result;
  if(array.length <= startIndex) return result;

  //Search the KEY in array from the startIndex position
  let index = array.indexOf(key, startIndex);

  //If not found any index return []
  if(index < 0) return result;

  //If it finds a key, insert its position in the result array
  result.push(index);

  //Recursive call updating the value of startIndex
  result = result.concat(indexOfFull(array, key, ++index));

  //Return array with found indexes
  return result;
}

const array = ["test234", "test9495", "test234", "test93992", "test234"];
console.log(indexOfFull(array, "test234")); 
//Result => [0, 2, 4]

Cristian
  • 51
  • 4
0

function indexesOf(str, array){
        var out = [];
        for (i=0;i<array.length;i++) {
            if (str == array[i] ) {
                out.push(i);
            };
        }
        return out;
    }
var arr = ["test234", "test9495", "test234", "test93992", "test234"];    
str = "test234";
console.log(indexesOf(str, arr));
Karra Max
  • 112
  • 2
  • 9