Or for those looking for a one-liner (simple and functional) compatible with current browsers:
let a = ["1", "1", "2", "3", "3", "1"];
let unique = a.filter((item, i, ar) => ar.indexOf(item) === i);
console.log(unique);
Update 2021
I would recommend checking out Charles Clayton’s answer, as of recent changes to JS there are even more concise ways to do this.
Update 18-04-2017
It appears as though ‘Array.prototype.includes’ now has widespread support in the latest versions of the mainline browsers (compatibility)
Update 29-07-2015:
There are plans in the works for browsers to support a standardized ‘Array.prototype.includes’ method, which although does not directly answer this question; is often related.
Usage:
["1", "1", "2", "3", "3", "1"].includes("2"); // true
Pollyfill (browser support, source from mozilla):
// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(searchElement, fromIndex) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If len is 0, return false.
if (len === 0) {
return false;
}
// 4. Let n be ? ToInteger(fromIndex).
// (If fromIndex is undefined, this step produces the value 0.)
var n = fromIndex | 0;
// 5. If n ≥ 0, then
// a. Let k be n.
// 6. Else n < 0,
// a. Let k be len + n.
// b. If k < 0, let k be 0.
var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
// 7. Repeat, while k < len
while (k < len) {
// a. Let elementK be the result of ? Get(O, ! ToString(k)).
// b. If SameValueZero(searchElement, elementK) is true, return true.
// c. Increase k by 1.
// NOTE: === provides the correct "SameValueZero" comparison needed here.
if (o[k] === searchElement) {
return true;
}
k++;
}
// 8. Return false
return false;
}
});
}
With JavaScript 1.6 / ECMAScript 5 you can use the native filter
method of an Array in the following way to get an array with unique values:
function onlyUnique(value, index, array) {
return array.indexOf(value) === index;
}
// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter(onlyUnique);
console.log(unique); // ['a', 1, 2, '1']
The native method filter
will loop through the array and leave only those entries that pass the given callback function onlyUnique
.
onlyUnique
checks, if the given value is the first occurring. If not, it must be a duplicate and will not be copied.
This solution works without any extra library like jQuery or prototype.js.
It works for arrays with mixed value types too.
For old Browsers (<ie9), that do not support the native methods filter
and indexOf
you can find work arounds in the MDN documentation for filter and indexOf.
If you want to keep the last occurrence of a value, simply replace indexOf
with lastIndexOf
.
With ES6 this can be shorten to:
// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((value, index, array) => array.indexOf(value) === index);
console.log(unique); // unique is ['a', 1, 2, '1']
Thanks to Camilo Martin for hint in comment.
ES6 has a native object Set
to store unique values. To get an array with unique values you could now do this:
var myArray = ['a', 1, 'a', 2, '1'];
let unique = [...new Set(myArray)];
console.log(unique); // unique is ['a', 1, 2, '1']
The constructor of Set
takes an iterable object, like an Array, and the spread operator ...
transform the set back into an Array. Thanks to Lukas Liese for hint in comment.
Mzzzzzz
4,7317 gold badges29 silver badges47 bronze badges
answered Jan 21, 2013 at 12:46
TLindigTLindig
47.2k3 gold badges27 silver badges31 bronze badges
19
Updated answer for ES6/ES2015: Using the Set and the spread operator (thanks le-m), the single line solution is:
let uniqueItems = [...new Set(items)]
Which returns
[4, 5, 6, 3, 2, 23, 1]
mikemaccana
107k96 gold badges383 silver badges482 bronze badges
answered Oct 14, 2015 at 9:42
A.T.A.T.
24.2k8 gold badges44 silver badges65 bronze badges
5
I split all answers to 4 possible solutions:
- Use object
{ }
to prevent duplicates - Use helper array
[ ]
- Use
filter + indexOf
- Bonus! ES6
Sets
method.
Here’s sample codes found in answers:
Use object { }
to prevent duplicates
function uniqueArray1( ar ) {
var j = {};
ar.forEach( function(v) {
j[v+ '::' + typeof v] = v;
});
return Object.keys(j).map(function(v){
return j[v];
});
}
Use helper array [ ]
function uniqueArray2(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
a.push(arr[i]);
return a;
}
Use filter + indexOf
function uniqueArray3(a) {
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
// usage
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']
return unique;
}
Use ES6 [...new Set(a)]
function uniqueArray4(a) {
return [...new Set(a)];
}
And I wondered which one is faster. I’ve made sample Google Sheet to test functions. Note: ECMA 6 is not avaliable in Google Sheets, so I can’t test it.
Here’s the result of tests:
I expected to see that code using object { }
will win because it uses hash. So I’m glad that tests showed the best results for this algorithm in Chrome and IE. Thanks to @rab for the code.
Update 2020
Google Script enabled ES6 Engine. Now I tested the last code with Sets
and it appeared faster than the object method.
answered Mar 27, 2017 at 12:24
Max MakhrovMax Makhrov
16.9k5 gold badges55 silver badges79 bronze badges
3
You can also use underscore.js.
console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>
which will return:
[1, 2, 3, 4]
Ruslan López
4,4131 gold badge26 silver badges37 bronze badges
answered Jul 11, 2012 at 16:25
kornfridgekornfridge
5,0626 gold badges28 silver badges40 bronze badges
5
One Liner, Pure JavaScript
With ES6 syntax
list = list.filter((x, i, a) => a.indexOf(x) == i)
x --> item in array
i --> index of item
a --> array reference, (in this case "list")
With ES5 syntax
list = list.filter(function (x, i, a) {
return a.indexOf(x) == i;
});
Browser Compatibility: IE9+
answered Sep 1, 2016 at 13:32
VamsiVamsi
9,4206 gold badges38 silver badges46 bronze badges
0
Remove duplicates using Set
.
Array
with duplicates
const withDuplicates = [2, 2, 5, 5, 1, 1, 2, 2, 3, 3];
Get a new array without duplicates by using Set
const withoutDuplicates = Array.from(new Set(withDuplicates));
A shorter version
const withoutDuplicates = [...new Set(withDuplicates)];
Result: [2, 5, 1, 3]
answered Jan 26, 2022 at 14:39
mdmundomdmundo
1,8522 gold badges21 silver badges37 bronze badges
2
Many of the answers here may not be useful to beginners. If de-duping an array is difficult, will they really know about the prototype chain, or even jQuery?
In modern browsers, a clean and simple solution is to store data in a Set, which is designed to be a list of unique values.
const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
const uniqueCars = Array.from(new Set(cars));
console.log(uniqueCars);
The Array.from
is useful to convert the Set back to an Array so that you have easy access to all of the awesome methods (features) that arrays have. There are also other ways of doing the same thing. But you may not need Array.from
at all, as Sets have plenty of useful features like forEach.
If you need to support old Internet Explorer, and thus cannot use Set, then a simple technique is to copy items over to a new array while checking beforehand if they are already in the new array.
// Create a list of cars, with duplicates.
var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
// Create a list of unique cars, to put a car in if we haven't already.
var uniqueCars = [];
// Go through each car, one at a time.
cars.forEach(function (car) {
// The code within the following block runs only if the
// current car does NOT exist in the uniqueCars list
// - a.k.a. prevent duplicates
if (uniqueCars.indexOf(car) === -1) {
// Since we now know we haven't seen this car before,
// copy it to the end of the uniqueCars list.
uniqueCars.push(car);
}
});
To make this instantly reusable, let’s put it in a function.
function deduplicate(data) {
if (data.length > 0) {
var result = [];
data.forEach(function (elem) {
if (result.indexOf(elem) === -1) {
result.push(elem);
}
});
return result;
}
}
So to get rid of the duplicates, we would now do this.
var uniqueCars = deduplicate(cars);
The deduplicate(cars)
part becomes the thing we named result when the function completes.
Just pass it the name of any array you like.
OXiGEN
1,91124 silver badges19 bronze badges
answered Jan 15, 2014 at 6:56
Seth HolladaySeth Holladay
8,8113 gold badges34 silver badges42 bronze badges
4
Using ES6 new Set
var array = [3,7,5,3,2,5,2,7];
var unique_array = [...new Set(array)];
console.log(unique_array); // output = [3,7,5,2]
Using For Loop
var array = [3,7,5,3,2,5,2,7];
for(var i=0;i<array.length;i++) {
for(var j=i+1;j<array.length;j++) {
if(array[i]===array[j]) {
array.splice(j,1);
}
}
}
console.log(array); // output = [3,7,5,2]
Jerome
7341 gold badge8 silver badges28 bronze badges
answered Dec 24, 2021 at 4:58
I have since found a nice method that uses jQuery
arr = $.grep(arr, function(v, k){
return $.inArray(v ,arr) === k;
});
Note: This code was pulled from Paul Irish’s duck punching post — I forgot to give credit
answered Jul 12, 2012 at 15:41
MottieMottie
83.8k30 gold badges125 silver badges241 bronze badges
2
Magic
a.filter(e=>!(t[e]=e in t))
O(n) performance — we assume your array is in a
and t={}
. Explanation here (+Jeppe impr.)
answered Nov 28, 2018 at 19:45
Kamil KiełczewskiKamil Kiełczewski
83.1k29 gold badges359 silver badges335 bronze badges
5
The simplest, and fastest (in Chrome) way of doing this:
Array.prototype.unique = function() {
var a = [];
for (var i=0, l=this.length; i<l; i++)
if (a.indexOf(this[i]) === -1)
a.push(this[i]);
return a;
}
Simply goes through every item in the array, tests if that item is already in the list, and if it’s not, pushes to the array that gets returned.
According to JSBench, this function is the fastest of the ones I could find anywhere — feel free to add your own though.
The non-prototype version:
function uniques(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
a.push(arr[i]);
return a;
}
Sorting
When also needing to sort the array, the following is the fastest:
Array.prototype.sortUnique = function() {
this.sort();
var last_i;
for (var i=0;i<this.length;i++)
if ((last_i = this.lastIndexOf(this[i])) !== i)
this.splice(i+1, last_i-i);
return this;
}
or non-prototype:
function sortUnique(arr) {
arr.sort();
var last_i;
for (var i=0;i<arr.length;i++)
if ((last_i = arr.lastIndexOf(arr[i])) !== i)
arr.splice(i+1, last_i-i);
return arr;
}
This is also faster than the above method in most non-Chrome browsers.
tagurit
4945 silver badges13 bronze badges
answered Jan 30, 2014 at 0:10
Joeytje50Joeytje50
18.6k14 gold badges63 silver badges94 bronze badges
8
We can do this using ES6 sets:
var duplicatesArray = [1, 2, 3, 4, 5, 1, 1, 1, 2, 3, 4];
var uniqueArray = [...new Set(duplicatesArray)];
console.log(uniqueArray); // [1,2,3,4,5]
vsync
116k56 gold badges302 silver badges393 bronze badges
answered Apr 9, 2018 at 3:49
chinmayanchinmayan
1,29414 silver badges13 bronze badges
["Defects", "Total", "Days", "City", "Defects"].reduce(function(prev, cur) {
return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
}, []);
[0,1,2,0,3,2,1,5].reduce(function(prev, cur) {
return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
}, []);
answered Sep 19, 2014 at 19:09
sergeyzsergeyz
1,33910 silver badges14 bronze badges
1
This has been answered a lot, but it didn’t address my particular need.
Many answers are like this:
a.filter((item, pos, self) => self.indexOf(item) === pos);
But this doesn’t work for arrays of complex objects.
Say we have an array like this:
const a = [
{ age: 4, name: 'fluffy' },
{ age: 5, name: 'spot' },
{ age: 2, name: 'fluffy' },
{ age: 3, name: 'toby' },
];
If we want the objects with unique names, we should use array.prototype.findIndex
instead of array.prototype.indexOf
:
a.filter((item, pos, self) => self.findIndex(v => v.name === item.name) === pos);
answered Sep 6, 2019 at 15:23
DaveDave
1,8881 gold badge16 silver badges25 bronze badges
3
After looking into all the 90+ answers here, I saw there is room for one more:
Array.includes has a very handy second-parameter: «fromIndex», so by using it, every iteration of the filter
callback method will search the array, starting from [current index] + 1
which guarantees not to include currently filtered item in the lookup and also saves time.
Note — this solution does not retain the order, as it removed duplicated items from left to right, but it wins the
Set
trick if the Array is a collection of Objects.
// 🚩 🚩 🚩
var list = [0,1,2,2,3,'a','b',4,5,2,'a']
console.log(
list.filter((v,i) => !list.includes(v,i+1))
)
// [0,1,3,"b",4,5,2,"a"]
Explanation:
For example, lets assume the filter
function is currently iterating at index 2
) and the value at that index happens to be 2
. The section of the array that is then scanned for duplicates (includes
method) is everything after index 2 (i+1
):
👇 👇
[0, 1, 2, 2 ,3 ,'a', 'b', 4, 5, 2, 'a']
👆 |---------------------------|
And since the currently filtered item’s value 2
is included in the rest of the array, it will be filtered out, because of the leading exclamation mark which negates the filter rule.
If order is important, use this method:
answered Oct 3, 2020 at 19:57
vsyncvsync
116k56 gold badges302 silver badges393 bronze badges
2
This prototype getUnique
is not totally correct, because if i have a Array like: ["1",1,2,3,4,1,"foo"]
it will return ["1","2","3","4"]
and "1"
is string and 1
is a integer; they are different.
Here is a correct solution:
Array.prototype.unique = function(a){
return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });
using:
var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();
The above will produce ["1",2,3,4,1,"foo"]
.
Gajus
67.9k70 gold badges271 silver badges435 bronze badges
answered Jul 27, 2012 at 16:57
3
You can simlply use the built-in functions Array.prototype.filter()
and Array.prototype.indexOf()
array.filter((x, y) => array.indexOf(x) == y)
var arr = [1, 2, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 6, 9];
var newarr = arr.filter((x, y) => arr.indexOf(x) == y);
console.log(newarr);
answered Sep 19, 2021 at 17:54
BlackjackBlackjack
1,2621 gold badge14 silver badges20 bronze badges
[...new Set(duplicates)]
This is the simplest one and referenced from MDN Web Docs.
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)]) // [2, 3, 4, 5, 6, 7, 32]
answered Jul 19, 2019 at 12:18
ifelse.codesifelse.codes
2,22923 silver badges21 bronze badges
2
Without extending Array.prototype (it is said to be a bad practice) or using jquery/underscore, you can simply filter
the array.
By keeping last occurrence:
function arrayLastUnique(array) {
return array.filter(function (a, b, c) {
// keeps last occurrence
return c.indexOf(a, b + 1) < 0;
});
},
or first occurrence:
function arrayFirstUnique(array) {
return array.filter(function (a, b, c) {
// keeps first occurrence
return c.indexOf(a) === b;
});
},
Well, it’s only javascript ECMAScript 5+, which means only IE9+, but it’s nice for a development in native HTML/JS (Windows Store App, Firefox OS, Sencha, Phonegap, Titanium, …).
answered Apr 17, 2013 at 16:48
CœurCœur
36.8k25 gold badges192 silver badges262 bronze badges
1
Array.prototype.getUnique = function() {
var o = {}, a = []
for (var i = 0; i < this.length; i++) o[this[i]] = 1
for (var e in o) a.push(e)
return a
}
answered Dec 25, 2009 at 5:11
ephemientephemient
197k38 gold badges278 silver badges391 bronze badges
3
That’s because 0
is a falsy value in JavaScript.
this[i]
will be falsy if the value of the array is 0 or any other falsy value.
answered Dec 25, 2009 at 4:32
Luca MatteisLuca Matteis
29.1k19 gold badges114 silver badges169 bronze badges
1
Now using sets you can remove duplicates and convert them back to the array.
var names = ["Mike","Matt","Nancy", "Matt","Adam","Jenny","Nancy","Carl"];
console.log([...new Set(names)])
Another solution is to use sort & filter
var names = ["Mike","Matt","Nancy", "Matt","Adam","Jenny","Nancy","Carl"];
var namesSorted = names.sort();
const result = namesSorted.filter((e, i) => namesSorted[i] != namesSorted[i+1]);
console.log(result);
answered May 17, 2019 at 8:18
Krishnadas PCKrishnadas PC
5,8112 gold badges53 silver badges50 bronze badges
If you’re using Prototype framework there is no need to do ‘for’ loops, you can use http://prototypejs.org/doc/latest/language/Array/prototype/uniq/ like this:
var a = Array.uniq();
Which will produce a duplicate array with no duplicates. I came across your question searching a method to count distinct array records so after uniq()
I used size()
and there was my simple result.
p.s. Sorry if i mistyped something
edit: if you want to escape undefined records you may want to add compact()
before, like this:
var a = Array.compact().uniq();
tagurit
4945 silver badges13 bronze badges
answered Nov 1, 2011 at 13:18
DecebalDecebal
1,3711 gold badge21 silver badges36 bronze badges
2
I had a slightly different problem where I needed to remove objects with duplicate id properties from an array. this worked.
let objArr = [{
id: '123'
}, {
id: '123'
}, {
id: '456'
}];
objArr = objArr.reduce((acc, cur) => [
...acc.filter((obj) => obj.id !== cur.id), cur
], []);
console.log(objArr);
demo
5,97618 gold badges73 silver badges149 bronze badges
answered Oct 11, 2018 at 13:30
shunryu111shunryu111
5,7774 gold badges26 silver badges16 bronze badges
0
If you’re okay with extra dependencies, or you already have one of the libraries in your codebase, you can remove duplicates from an array in place using LoDash (or Underscore).
Usage
If you don’t have it in your codebase already, install it using npm:
npm install lodash
Then use it as follows:
import _ from 'lodash';
let idArray = _.uniq ([
1,
2,
3,
3,
3
]);
console.dir(idArray);
Out:
[ 1, 2, 3 ]
answered Jun 11, 2018 at 11:34
1
I’m not sure why Gabriel Silveira wrote the function that way but a simpler form that works for me just as well and without the minification is:
Array.prototype.unique = function() {
return this.filter(function(value, index, array) {
return array.indexOf(value, index + 1) < 0;
});
};
or in CoffeeScript:
Array.prototype.unique = ->
this.filter( (value, index, array) ->
array.indexOf(value, index + 1) < 0
)
answered Jun 7, 2013 at 3:30
Dan FoxDan Fox
1051 silver badge1 bronze badge
Finding unique Array values in simple method
function arrUnique(a){
var t = [];
for(var x = 0; x < a.length; x++){
if(t.indexOf(a[x]) == -1)t.push(a[x]);
}
return t;
}
arrUnique([1,4,2,7,1,5,9,2,4,7,2]) // [1, 4, 2, 7, 5, 9]
answered Jan 7, 2016 at 13:33
2
It appears we have lost Rafael’s answer, which stood as the accepted answer for a few years. This was (at least in 2017) the best-performing solution if you don’t have a mixed-type array:
Array.prototype.getUnique = function(){
var u = {}, a = [];
for (var i = 0, l = this.length; i < l; ++i) {
if (u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
If you do have a mixed-type array, you can serialize the hash key:
Array.prototype.getUnique = function() {
var hash = {}, result = [], key;
for ( var i = 0, l = this.length; i < l; ++i ) {
key = JSON.stringify(this[i]);
if ( !hash.hasOwnProperty(key) ) {
hash[key] = true;
result.push(this[i]);
}
}
return result;
}
Adam Katz
14.1k4 gold badges66 silver badges82 bronze badges
answered Jul 18, 2013 at 1:52
JasonJason
2,0732 gold badges14 silver badges7 bronze badges
strange this hasn’t been suggested before.. to remove duplicates by object key (id
below) in an array you can do something like this:
const uniqArray = array.filter((obj, idx, arr) => (
arr.findIndex((o) => o.id === obj.id) === idx
))
answered Feb 1, 2018 at 16:36
daviestardaviestar
4,5113 gold badges29 silver badges46 bronze badges
2
For an object-based array with some unique id’s, I have a simple solution through which you can sort in linear complexity
function getUniqueArr(arr){
const mapObj = {};
arr.forEach(a => {
mapObj[a.id] = a
})
return Object.values(mapObj);
}
answered Feb 29, 2020 at 15:30
0
Время на прочтение
5 мин
Количество просмотров 45K
Массивы являются одной из самых популярных структур данных в JavaScript, потому что они используются для хранения данных. Кроме этого, массивы дают много возможностей для работы с этими самыми данными. Понимая, что для тех, кто находится в начале пути изучения JavaScript, массивы являются одной из самых основных тем, в этой статье я хотел бы познакомить вас с некоторыми полезными трюками, о которых вы могли не знать. Давайте начнем.
1. Как в массиве оставить только уникальные значения
Это очень популярный вопрос во время интервью на позицию Javascript-разработчика. Вот быстрое и простое решение этой задачки. Для начала вам нужно получить уникальные значения массива, для этого можно использовать new Set()
(прим. перев.: структура данных Set хранит только уникальные значения). Далее нужно преобразовать структуру данных Set в массив. Я хочу познакомить вас с двумя способами, как это можно сделать: первый – с помощью метода from()
, второй – с помощью оператора spread ("…"
).
const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
// Первый метод
const uniqueFruits = Array.from(new Set(fruits));
console.log(uniqueFruits); // вернет ['banana', 'apple', 'orange', 'watermelon', 'grape']
// Второй метод
const uniqueFruits2 = [...new Set(fruits)];
console.log(uniqueFruits2); // вернет ['banana', 'apple', 'orange', 'watermelon', 'grape']
Легко, правда?
2. Как заменить значения в массиве
Бывают такие ситуации, когда нужно заменить значения в массиве другими значениями. Для этого существует хороший метод, о котором вы, возможно, не знали – метод splice(start, value to remove, values to add)
, где start
– номер индекса, начиная с которого мы хотим удалить элементы массива, value to remove
– число элементов, которые мы хотим удалить, а values to add
– элементы, которые мы хотим вставить на место удаленных:
const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
fruits.splice(0, 2, 'potato', 'tomato');
console.log(fruits); // вернет ["potato", "tomato", "orange", "watermelon", "apple", "orange", "grape", "apple"]
3. Как трансформировать массив, не используя метод map()
Наверное, все знают метод массива map()
, но есть и другое решение, которое может быть использовано для получения аналогичного эффекта и чистого кода. Для этого мы можем воспользоваться методом from()
:
const friends = [
{ name: 'John', age: 22 },
{ name: 'Peter', age: 23 },
{ name: 'Mark', age: 24 },
{ name: 'Maria', age: 22 },
{ name: 'Monica', age: 21 },
{ name: 'Martha', age: 19 },
]
const friendsNames = Array.from(friends, ({name}) => name);
console.log(friendsNames); // вернет ['John', 'Peter', 'Mark', 'Maria', 'Monica', 'Martha']
4. Как быстро очистить массив
Например, у нас есть массив, в котором много элементов. Нам нужно его очистить (неважно для какой цели), при этом мы не хотим удалять элементы один за другим. Это очень просто сделать одной строчкой кода. Чтобы очистить массив, нам нужно установить длину массива в 0, и всё!
const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
fruits.length = 0;
console.log(fruits); // вернет []
5. Как преобразовать массив в объект
Бывает такая ситуация: у нас есть массив, но нам нужен объект (опять неважно для какой цели) с этими данными, и самый быстрый способ преобразовать массив в объект – это использовать оператор spread ("..."
):
const fruits = ['banana', 'apple', 'orange', 'watermelon', 'apple', 'orange', 'grape', 'apple'];
const fruitsObj = { ...fruits };
console.log(fruitsObj); // вернет {0: 'banana', 1: 'apple', 2: 'orange', 3: 'watermelon', 4: 'apple', 5: 'orange', 6: 'grape', 7: 'apple'}
6. Как заполнить массив одинаковыми значениями
Бывают разные ситуации, когда мы хотим создать массив и заполнить его некоторыми значениями, или нам нужен массив с одинаковыми значениями. Метод fill()
для подобных задач является отличным решением:
const newArray = new Array(10).fill('1');
console.log(newArray); // вернет ["1", "1", "1", "1", "1", "1", "1", "1", "1", "1"]
7. Как объединить более двух массивов
Вы знаете, как объединить массивы в один, не используя метод concat()
? Существует простой способ объединить любое количество массивов в один массив одной строчкой кода. Как вы, вероятно, уже поняли, оператор spread ("..."
) является довольно полезным инструментом при работе с массивами, как и в этом случае:
const fruits = ['apple', 'banana', 'orange'];
const meat = ['poultry', 'beef', 'fish'];
const vegetables = ['potato', 'tomato', 'cucumber'];
const food = [...fruits, ...meat, ...vegetables];
console.log(food); // вернет ["apple", "banana", "orange", "poultry", "beef", "fish", "potato", "tomato", "cucumber"]
8. Как найти пересечение двух массивов
С этой задачей вы можете столкнуться на любом JavaScript-собеседовании, потому что ее решение показывает ваши знания методов массива, а также то, как вы мыслите. Чтобы найти общие значения двух массивов, мы будем использовать один из ранее рассмотренных методов в этой статье, чтобы убедиться, что значения в массиве, который мы проверяем, не дублируются. Кроме этого, мы воспользуемся методами filter()
и includes()
. В результате мы получим массив с элементами, которые представлены в обоих массивах:
const numOne = [0, 2, 4, 6, 8, 8];
const numTwo = [1, 2, 3, 4, 5, 6];
const duplicatedValues = [...new Set(numOne)].filter(item => numTwo.includes(item));
console.log(duplicatedValues); // вернет [2, 4, 6]
9. Как удалить ложные значения из массива
Для начала, давайте определим ложные значения. В Javascript ложными значениями являются: false
, 0, «», null
, NaN
и undefined
. Теперь мы можем выяснить, как удалить такие значения из нашего массива. Для достижения этой цели нам потребуется метод filter()
:
const mixedArr = [0, 'blue', '', NaN, 9, true, undefined, 'white', false];
const trueArr = mixedArr.filter(Boolean);
console.log(trueArr); // вернет ["blue", 9, true, "white"]
10. Как получить рандомное значение массива
Иногда нам нужно выбрать рандомное значение массива. Чтобы решение было простым, коротким и быстрым, мы можем получить случайный номер индекса в соответствии с длиной массива. Посмотрите на этот пример:
const colors = ['blue', 'white', 'green', 'navy', 'pink', 'purple', 'orange', 'yellow', 'black', 'brown'];
const randomColor = colors[(Math.floor(Math.random() * (colors.length)))];
console.log(randomColor); // вернет рандомный цвет из массива
11. Как развернуть массив в обратную сторону
Когда нам нужно «перевернуть» наш массив, нет необходимости создавать его через сложные циклы и функции, потому что есть простой метод массива reverse()
, который делает все это за нас, и одной строчкой кода мы можем «перевернуть» наш массив:
const colors = ['blue', 'white', 'green', 'navy', 'pink', 'purple', 'orange', 'yellow', 'black', 'brown'];
const reversedColors = colors.reverse();
console.log(reversedColors); // вернет ["brown", "black", "yellow", "orange", "purple", "pink", "navy", "green", "white", "blue"]
12. Метод lastIndexOf()
В JavaScript есть интересный метод lastIndexOf(elem)
, который позволяет найти индекс последнего вхождения элемента elem
. Например, если наш массив имеет дублированные значения, мы можем найти позицию последнего вхождения в него. Взгляните на следующий пример кода:
const nums = [1, 5, 2, 6, 3, 5, 2, 3, 6, 5, 2, 7];
const lastIndex = nums.lastIndexOf(5);
console.log(lastIndex); // вернет 9
13. Как просуммировать все значения в массиве
Еще один популярный вопрос во время собеседования на позицию JavaScript-разработчика. Сумму всех элементов можно найти одной строчкой кода, если знать метод reduce()
:
const nums = [1, 5, 2, 6];
const sum = nums.reduce((x, y) => x + y);
console.log(sum); // вернет 14
Заключение
В этой статье я познакомил вас с 13 полезными приёмами, которые помогут вам писать чистый и краткий код. Кроме этого, не забывайте, что есть много различных трюков, которые вы можете использовать в Javascript и которые стоит изучить не только для работы с массивами, но и для других структур данных. Я надеюсь, что вам понравились решения, представленные в статье, и вы будете использовать их для улучшения процесса разработки.
Приятного написания кода!
Phi Byă
Posted on Oct 2, 2021
• Updated on Feb 21, 2022
Without further intro, let’s just dive into the solutions: use Array.prototype.reduce
AND (Set
for primitive values OR Map
for objects).
Here are the code:
For an array of primitive values
const uniqueArray = (array) => {
return Array.from(
array.reduce((set, e) => set.add(e), new Set())
)
}
console.log(uniqueArray([1,2,2,3,3,3])) // [1, 2, 3]
//OR simply
const uniqueArray = (array) => Array.from(new Set(array))
Enter fullscreen mode
Exit fullscreen mode
For an array of objects
const uniqueArray = (objects, uniqueBy, keepFirst = true) => {
return Array.from(
objects.reduce((map, e) => {
let key = uniqueBy.map(key => [e[key], typeof e[key]]).flat().join('-')
if (keepFirst && map.has(key)) return map
return map.set(key, e)
}, new Map()).values()
)
}
let array = [
{a: 1, b: 2, c: 1},
{a: 1, b: 2, c: 2},
{a: 1, b: 3, c: 3}
]
console.log(uniqueArray(array, ["a"], true)) // [ { a: 1, b: 2, c: 1 } ]
console.log(uniqueArray(array, ["a"], false)) // [ { a: 1, b: 3, c: 3 } ]
console.log(uniqueArray(array, ["a", "b"], true)) // [ { a: 1, b: 2, c: 1 }, { a: 1, b: 3, c: 3 } ]
console.log(uniqueArray(array, ["a", "b"], false)) // [ { a: 1, b: 2, c: 2 }, { a: 1, b: 3, c: 3 } ]
Enter fullscreen mode
Exit fullscreen mode
The reason we need to use Set
and Map
is because of the performance. You may have come across many implementations of getting unique values from an array in Javascript. Many of them will look like this:
- Create a new array, check if the element is not in the new array then push it to the new array, or
let array = [1,2,2,3,3,3]
let uniqueArray = []
array.forEach(e => {
if (!uniqueArray.includes(e)) uniqueArray.push(e)
})
console.log(uniqueArray) // [1, 2, 3]
Enter fullscreen mode
Exit fullscreen mode
- Use filter, check if the element appear the first time in the array then keep it, or
let array = [1,2,2,3,3,3]
let uniqueArray = array.filter((e, index) => array.indexOf(e) === index)
console.log(uniqueArray) // [1, 2, 3]
Enter fullscreen mode
Exit fullscreen mode
- Use reduce, check if the element is not in the new array then use array destruction with the new element
let array = [1,2,2,3,3,3]
let uniqueArray = array.reduce((newArray, e) => {
if (newArray.includes(e)) return newArray;
return [...newArray, e]
}, [])
console.log(uniqueArray) // [1, 2, 3]
Enter fullscreen mode
Exit fullscreen mode
The problem is: they are slow. Let’s do a quick benchmark. The benchmark below creates 5 arrays with 100,000 elements each. The first array contains all unique elements. The second array has each element appears 2 times. The third array has each element appears 3 times, and so on. All arrays are shuffled before getting unique values. We will use different methods to get the unique values in the array.
const usePush = (array) => {
let uniqueArray = []
array.forEach(e => {
if (!uniqueArray.includes(e)){
uniqueArray.push(e)
}
})
return uniqueArray
}
const useFilter = (array) => {
return array.filter((e, index) => array.indexOf(e) === index)
}
const useReduceDestruct = (array) => {
return array.reduce((pre, cur) => {
if (pre.includes(cur)) return pre;
return [...pre, cur]
}, [])
}
const useReduceSet = (array) => {
return Array.from(
array.reduce((set, e) => set.add(e), new Set())
)
}
//Create 5 big arrays with different number of duplicates for each element
let bigArrays = [1,2,3,4,5].map(duplicates => {
//duplicates = 1 means the array is unique
//duplicates = 2 means each element appears 2 times, and so on
return new Array(100000).fill(0)
.map((_, i) => ({
rand : Math.random(),
value : i - i % duplicates
}))
.sort((a,b) => a.rand - b.rand)//the array is random shuffled
.map(e => e.value)
})
bigArrays.forEach((array, index) =>{
console.log(`${index + 1} duplicate(s):`);
[usePush, useFilter, useReduceDestruct, useReduceSet].forEach(fn =>{
let startTime = Date.now()
fn(array)
console.log(`${fn.name}${' '.repeat(20 - fn.name.length)} finished in ${((Date.now() - startTime)/1000).toFixed(3)} seconds`)
})
})
Enter fullscreen mode
Exit fullscreen mode
Output:
1 duplicate(s):
usePush finished in 5.395 seconds
useFilter finished in 5.365 seconds
useReduceDestruct finished in 72.743 seconds
useReduceSet finished in 0.013 seconds
2 duplicate(s):
usePush finished in 2.694 seconds
useFilter finished in 3.555 seconds
useReduceDestruct finished in 19.220 seconds
useReduceSet finished in 0.008 seconds
3 duplicate(s):
usePush finished in 1.818 seconds
useFilter finished in 2.678 seconds
useReduceDestruct finished in 8.659 seconds
useReduceSet finished in 0.008 seconds
4 duplicate(s):
usePush finished in 1.339 seconds
useFilter finished in 2.155 seconds
useReduceDestruct finished in 4.933 seconds
useReduceSet finished in 0.006 seconds
5 duplicate(s):
usePush finished in 1.123 seconds
useFilter finished in 1.787 seconds
useReduceDestruct finished in 2.970 seconds
useReduceSet finished in 0.009 seconds
Enter fullscreen mode
Exit fullscreen mode
It is clear that the more duplication we have in the array, the faster the code runs. It is also obvious that using Array.prototype.reduce
and Set
is the fastest among all.
Bonus: Getting unique values from an array of objects using multiple-level object keys (nested properties):
const uniqueArray = (objects, uniqueBy, keepFirst = true) => {
const orderedObject = (value) => {
if (typeof value !== "object") return value;
return Object.keys(value).sort().reduce((pre, key) => {
pre[key] = orderedObject(value[key])
return pre
}, {})
}
return Array.from(
objects.reduce((map, e) => {
let key = uniqueBy.map(prop => {
let value = prop.split(".").reduce((object, cur) => object?.[cur], e)
return [JSON.stringify(orderedObject(value)), typeof value]
}).flat().join('-')
if (keepFirst && map.has(key)) return map
return map.set(key, e)
}, new Map()).values()
)
}
let array = [
{a: [{x: 1}, 1], b: 2},
{a: [{x: 1}, 1], b: 2},
{a: [{x: 1, y: 2}, 2], b: 2}
]
console.log(
JSON.stringify(uniqueArray(array, ["a.0", "b"])) //Unique by `object["a"][0]` and `object["b"]`
) // [{"a":[{"x":1},1],"b":2},{"a":[{"x":1,"y":2},2],"b":2}]
console.log(
JSON.stringify(uniqueArray(array, ["a.0.x", "b"])) //Unique by `object["a"][0]["x"]` and `object["b"]`
) // [{"a":[{"x":1},1],"b":2}]
Enter fullscreen mode
Exit fullscreen mode
In this post, We are going to learn how to Find Unique Values in an array of objects in JavaScript ES6 with an example. We will use Javascript Set that unique values collection, spread operator, and array.map() ,reduce() and simple for loop to get unique values.
1. Find Unique Values in array of object JavaScript ES6
A set object is a unique values collection of a different datatype which includes the primitive type or complex object literal, Array. It makes us iterate the elements in insertion order. In this JavaScript Example, We have used array.map() method will create a new array by selecting a desired property from the object array. The set constructor along with the spread operator selects unique property from a given array of objects.
let Employee = [ {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'} ] const uniqueVals = [...new Set(Employee.map(item => item.Empname))]; console.log(uniqueVals)
Output
[ 'John', 'jack', 'Racx' ]
2. Find all Unique values by key in Array of objects
In this example, we have found all unique values by key ‘Empname’ in all objects of the array by using the array.map() by selecting all the values. map constructor is used along with the spread operator to spread the array elements returned by the array.map() method.
let Employee = [ {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'} ] const key = 'Empname'; const uniqueVals = [...new Map(Employee.map(item => [item[key], item])).values()]; console.log(uniqueVals)
Output
[ { Empname: 'John', salary: 60000, EmpID: 1, Dep: 'Admin' }, { Empname: 'jack', salary: 50000, EmpID: 2, Dep: 'IT' }, { Empname: 'Racx', salary: 60000, EmpID: 4, Dep: 'IT' } ]
3. Find all unique values in Array of objects
In this JavaScript program Example, We will discuss how to Find Unique Values in array of objects JavaScript by using array.filter() to get all uniques values by key ‘EmpId’ in all objects in the array.
let Employee = [ {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'} ] let uniqueVals = Employee.filter((value, index, self) => self.findIndex((Emp) => Emp.EmpID === value.EmpID) === index); console.log(uniqueVals)
Output
[ { Empname: 'John', salary: 60000, EmpID: 1, Dep: 'Admin' }, { Empname: 'jack', salary: 50000, EmpID: 2, Dep: 'IT' }, { Empname: 'Racx', salary: 60000, EmpID: 4, Dep: 'IT' } ]
4. Array.from() to Find unique values in Array of objects
In this example, We have used array.map() to get a new array that contains EmpID and set constructor to get uniques EmpID from an array of objects. The used array.from() instead of spread operator,array.from() is an static method that create an array object from array=like or iterable objects(string,array,map,set).
let Employee = [ {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'} ] let uniqueVals = Array.from(new Set(Employee.map((item => item.EmpID)))) console.log(uniqueVals)
Output
5. Reduce() to Find unique Values in array of object
To find unique values in all object in an array by EmpID, We have used array.map() that create a new array by EmpID from the Employee object. The array.reduce() method call a callback function for each element of the array and the result returned by the callback function after each iteration pass to the accumulator of reduce function that is used for the next iteration.
let Employee = [ {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'John', salary: 60000,EmpID:1,Dep:'Admin'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'jack', salary: 50000,EmpID:2,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'}, {Empname: 'Racx', salary: 60000,EmpID:4,Dep:'IT'} ] let uniqueVals = Object.keys(Employee.reduce((result,{EmpID}) => (result[EmpID]='', result) , {})) console.log(uniqueVals)
Output
6. Reduce() to Find unique value in Array of object
In this Javascript example to get the unique value of the property we have used reduce() function along with the spread operator that is used to spread the element.In the last step used a new set constructor to get unique values of EmpID.Let us understand with examples
let uniqueVals = [...new Set(Employee.reduce((res, Emp) => [...res, Emp.EmpID], []))]; console.log(uniqueVals)
Output
7. For loop to find unique value in Array of object
In this example, we have used simply for loop in javascript to find unique values in an array of objects.
var uniqueArr = []; var result = []; for( let i = 0; i < Employee.length; i++ ){ if( !uniqueArr[Employee[i].EmpID]){ result.push(Employee[i].EmpID); uniqueArr[Employee[i].EmpID] = 1; } } console.log(result)
Output
Summary
In this post, we have learned how to Find Unique Values in array of objects in JavaScript ES6.