JavaScript indexOf method with multiple values
Asked Answered
K

7

17

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"));
Keli answered 14/4, 2016 at 18:54 Comment(2)
Possible duplicate of How to find index of all occurrences of an element in array?Ivonneivor
This question is an exact duplicate, but I should mention that using a for loop is the most efficient solution to the task.Ivonneivor
P
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>");
  }
}
Pepperandsalt answered 14/4, 2016 at 18:57 Comment(5)
Can you make it as a prototype?Keli
@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.Ivonneivor
You really should be using === instead of == for this to be a fool proof answer. See thisIvonneivor
@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.Pepperandsalt
@Pepperandsalt 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.Fogy
I
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")));
Ivonneivor answered 14/4, 2016 at 19:1 Comment(0)
M
10

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.

Marylyn answered 3/10, 2019 at 8:36 Comment(2)
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.Septivalent
Thanks! If you're referring to (acc, v, i), they're just the accumulator, the value, and the index as described in the reduce documentation I linked. Or did you mean something else?Marylyn
S
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>');
Spermatocyte answered 14/4, 2016 at 18:59 Comment(1)
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.Ivonneivor
O
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);
Onset answered 3/10, 2019 at 8:3 Comment(0)
C
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]

Cultrate answered 28/1, 2021 at 16:34 Comment(0)
A
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));
Analogous answered 20/12, 2021 at 23:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.