I know how to do both things separately, but I'm sure there must be a way to combine them.
I have an array of categories, which I am extracting from an array of objects:
this.videoCategories = this.videos.map(v => v.category);
But of course there are duplicates in this array. So now I do
this.uniqueVideoCategories = this.videoCategories.filter((item, index) => {
return this.videoCategories.indexOf(item) === index;
});
Which works fine, I get an array of the categories without dupes. But I'm trying to learn and dry up the code a bit by stringing them together, and this does not work - yields empty array
constructor(private videoService: VideoService) {
this.videos = videoService.getVideos();
this.videoCategories = this.videos
.map(v => v.category)
.filter((item, index) => {
return this.videoCategories.indexOf(item) === index;
});
console.log(this.videoCategories);
}
JavaScript's Array#map() and Array#filter() functions are great when used together because they allow you to compose simple functions. For example, here's a basic use case for filter() : filtering out all numbers that are less than 100 from a numeric array. This function works fine on an array of numbers.
As the filter() method will return the array with the required elements. Now we will apply map() method to perform the specified operations on all elements of the array returned by filter() method.
Inside the filter()
you are checking the index inside the array of objects. You can use the third argument of filter()
method which will be the newly created array after map()
constructor(private videoService: VideoService) {
this.videos = videoService.getVideos();
this.videoCategories = this.videos
.map(v => v.category)
.filter((item, index, arr) => {
return arr.indexOf(item) === index;
});
console.log(this.videoCategories);
}
Instead of using filter()
and indexOf()
you can use Set
to remove duplicates. This will be the time-complexity O(N)
constructor(private videoService: VideoService) {
this.videos = videoService.getVideos();
this.videoCategories = [...new Set(this.videos.map(v => v.category))]
console.log(this.videoCategories);
}
Sometimes the solution is choosing the right data structure. ES6 has introduced Set
, which only contains unique objects.
Then you just do:
this.videoCategories = new Set(this.videos.map(v => v.category))
The uniqueness will be handled by browser implementation, instead of cluttering your codebase.
var videos = [
{ category: 'category1', title: 'Category 1'},
{ category: 'category1', title: 'Category 1'},
{ category: 'category1', title: 'Category 1'},
{ category: 'category2', title: 'Category 2'},
{ category: 'category2', title: 'Category 2'}
];
var categoryVideos =
videos
.map(v => v.category)
.filter((item, index, arr) => arr.indexOf(item) === index);
console.log(categoryVideos);
Array.prototype.filter
var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
callback
Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise. It accepts three arguments:
A new array with the elements that pass the test. If no elements pass the test, an empty array will be returned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With