peter flanagan
peter flanagan

Reputation: 9810

filter not returning index value javascript

I have a string in js and I want to record the index of each instance of the letter X.

I firstly tried using map but this just returned undefined along with the indexes, which I could have used, but would have required an additional function.

Then I used filter instead but unfortunately this is not returning the index. See example below:

const str = 'Hello there XXXX, how are you?';

let indexes = str.split('').filter((letter, index) => {
  if(letter === 'X'){
    return index;
  }
});

console.log(indexes);

Upvotes: 0

Views: 3457

Answers (5)

Dinesh Pandiyan
Dinesh Pandiyan

Reputation: 6299

Array.filter() creates a new array based on the result of the callback. If the return value in each callback is truthy, a new array with all the elements will be returned. If the return value of each callback in falsy, an empty array will be constructed.

So in this condition,

if(letter === 'X'){
  return index;
}

the index will be a number > 0 (truthy), so all 'X' will be returned as a new array. If the first character in your input is 'X', the return statement will be 0 which is falsy and that character won't be in the newly constructed array that filter() returns.

You could use write something like this instead,

const str = 'Hello there XXXX, how are you?';    
str.split('')
  .map((e, i) => e === 'X' ? {allow: true, index: i} : {allow: false})
  .filter(e => e.allow)
  .map(e => e.index)

Upvotes: 1

Pointy
Pointy

Reputation: 413916

You can do what you want without having to split the string first:

let xes = [];
for (let i = 0; (i = str.indexOf("X", i)) !== -1; xes.push(i++));

That finds each "X" with .indexOf(), starting from the last position plus 1.

Upvotes: 1

Andy
Andy

Reputation: 63570

You can use reduce instead. Here we supply an array as an initial value and push an index to it when the condition is met on an iteration.

const str = 'Hello there XXXX, how are you?';

let indexes = str.split('').reduce((arr, letter, index) => {
  if (letter === 'X') arr.push(index);
  return arr;
}, []);

console.log(indexes);

Upvotes: 2

MysterX
MysterX

Reputation: 2378

I think it would be better to fill indexes array by using forEach loop:

  const str = 'Hello there XXXX, how are you?';

  let indexes = [];
  str.split('').forEach((letter, index) => {
    if(letter === 'X'){
      indexes.push(index);
    }
  });

  console.log(indexes);

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386746

You could take Array.from, get every character of the string (as any other iterable) and map the index or -1 for not wanted character. Later filter only wanted indices.

You need two loops for this task, because the first takes the indices and the second filters the intermediate result. Your approach by taking only Array#filter returns the elements, but not the index of the the element. After filtering, the indices are gone.

const str = 'Hello there XXXX, how are you?';

let indexes = Array.from(str, (c, i) => c === 'X' ? i : -1).filter(i => i !== -1);

console.log(indexes);

Upvotes: 0

Related Questions