Reputation: 915
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
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
Reputation: 504
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.
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
Reputation: 1570
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)
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
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
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