Dickens
Dickens

Reputation: 915

Confusion with how indexOf works in JS

I am new to JS and was trying to learn how to properly work with indexOf in JS, that is, if you look at the code below:

var sandwiches = ['turkey', 'ham', 'turkey', 'tuna', 'pb&j', 'ham', 'turkey', 'tuna'];

var deduped = sandwiches.filter(function (sandwich, index) {
    return sandwiches.indexOf(sandwich) === index;
});

// Logs ["turkey", "ham", "tuna", "pb&j"]
console.log(deduped);

I am trying to remove duplicates but wanted to ask two questions. Firstly, in here return sandwiches.indexOf(sandwich) === index; why we need to use "== index;". Secondly, since indexOf returns index like 0, 1 or 2 ... then why when we console.log(deduped) we get array of names instead of array of indexes. Hope you got my points

Upvotes: 5

Views: 462

Answers (5)

John Coleman
John Coleman

Reputation: 51988

Perhaps the basic logic is easier to see at a glance if you use arrow notation:

const deduped = myArray => myArray.filter((x, i) => myArray.indexOf(x) === i);

The key point is that indexOf returns the index of the first occurrence of x. For that occurrence the result of the comparison will be true hence the element will be retained by the filter. For any subsequent occurrence the comparison will be false and the filter will reject it.

Upvotes: 2

Madhusudhan Aradya
Madhusudhan Aradya

Reputation: 504

  1. since the logic is to remove the duplicates from the array, in your example, you have "turkey" as duplicates. the "turkey" exists in position 0,2,6 so whenever you call indexOf("turkey") always returns 0 because the indexOf function returns the first occurrence of a substring. so for the elements in position 2 & 6 the condition fails. then it won't return that element.

  2. That is how the filter works in javascript. it evaluates the condition and returns true or false that indicates whether an element to be included in the new array or not, in your example the condition is return sandwiches.indexOf(sandwich) === index;

Upvotes: 3

Nikita Ryanov
Nikita Ryanov

Reputation: 1570

  1. Difference between === (identity) and == (equality): if type of compared values are different then === will return false, while == will try to convert values to the same type. So, in cases where you compare some values with known types it is better to use ===. (http://www.c-point.com/javascript_tutorial/jsgrpComparison.htm)

  2. You get as result an array of names instead of array of indexes because Array.filter do not change the values, but only filter them. The filter function in your case is return sandwiches.indexOf(sandwich) === index; which return true or false. If you want get the indexes of your items after deduplication, then use map after filter:

a.filter(...).map(function(item, idx) {return idx;})

Upvotes: 1

Alok Mali
Alok Mali

Reputation: 2881

@Dikens, indexOf gives the index of the element if found. And if the element is not found then it returns -1.

In your case you are filtering the array and storing the values in the deduped. That's why it is showing an array.

If you console the indexOf in the filter function then it will log the index of the element.

For example :

var deduped = sandwiches.filter(function (sandwich, index) {
   console.log(sandwiches.indexOf(sandwich));
   return sandwiches.indexOf(sandwich) === index;
});

Upvotes: 0

Mario Santini
Mario Santini

Reputation: 3003

You use a method of Javascript Array that is filter, this method take a function that returns a boolean.

The function filter returns a new Array based on the function passed applied to each entry.

If the function return true, then the entry is included in the new Array, otherwise is discarded.

As the functions check the indexOf an entry to be the current index is true for the first occurrency of the entry.

All the duplications will fail the expression as they are not the first index found by indexOf, so they are discarded.

Upvotes: 6

Related Questions