Как найти уникальные значения массива

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's user avatar

Mzzzzzz

4,7317 gold badges29 silver badges47 bronze badges

answered Jan 21, 2013 at 12:46

TLindig's user avatar

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's user avatar

mikemaccana

107k96 gold badges383 silver badges482 bronze badges

answered Oct 14, 2015 at 9:42

A.T.'s user avatar

A.T.A.T.

24.2k8 gold badges44 silver badges65 bronze badges

5

I split all answers to 4 possible solutions:

  1. Use object { } to prevent duplicates
  2. Use helper array [ ]
  3. Use filter + indexOf
  4. 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:
enter image description here

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 Makhrov's user avatar

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's user avatar

Ruslan López

4,4131 gold badge26 silver badges37 bronze badges

answered Jul 11, 2012 at 16:25

kornfridge's user avatar

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")

enter image description here

With ES5 syntax

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

Browser Compatibility: IE9+

Community's user avatar

answered Sep 1, 2016 at 13:32

Vamsi's user avatar

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

mdmundo's user avatar

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's user avatar

OXiGEN

1,91124 silver badges19 bronze badges

answered Jan 15, 2014 at 6:56

Seth Holladay's user avatar

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's user avatar

Jerome

7341 gold badge8 silver badges28 bronze badges

answered Dec 24, 2021 at 4:58

Surbhi Dighe's user avatar

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 :P

answered Jul 12, 2012 at 15:41

Mottie's user avatar

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łczewski's user avatar

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's user avatar

tagurit

4945 silver badges13 bronze badges

answered Jan 30, 2014 at 0:10

Joeytje50's user avatar

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's user avatar

vsync

116k56 gold badges302 silver badges393 bronze badges

answered Apr 9, 2018 at 3:49

chinmayan's user avatar

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

sergeyz's user avatar

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

Dave's user avatar

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

vsync's user avatar

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's user avatar

Gajus

67.9k70 gold badges271 silver badges435 bronze badges

answered Jul 27, 2012 at 16:57

Gabriel Silveira's user avatar

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

Blackjack's user avatar

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.codes's user avatar

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œur's user avatar

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

ephemient's user avatar

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 Matteis's user avatar

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 PC's user avatar

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's user avatar

tagurit

4945 silver badges13 bronze badges

answered Nov 1, 2011 at 13:18

Decebal's user avatar

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's user avatar

demo

5,97618 gold badges73 silver badges149 bronze badges

answered Oct 11, 2018 at 13:30

shunryu111's user avatar

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 ]

Constant Meiring's user avatar

answered Jun 11, 2018 at 11:34

NikeshPathania's user avatar

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 Fox's user avatar

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

Saravanan Rajaraman's user avatar

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's user avatar

Adam Katz

14.1k4 gold badges66 silver badges82 bronze badges

answered Jul 18, 2013 at 1:52

Jason's user avatar

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

daviestar's user avatar

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

Shreyansh Sharma's user avatar

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 и которые стоит изучить не только для работы с массивами, но и для других структур данных. Я надеюсь, что вам понравились решения, представленные в статье, и вы будете использовать их для улучшения процесса разработки.

Приятного написания кода!

Cover image for Methods to get unique values from arrays in Javascript and their performance

Phi Byă

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.

Понравилась статья? Поделить с друзьями:
  • Как исправить ошибку в павно error 017
  • Как найти плейлист вк с телефона
  • Ipv4 без доступа к интернету ipv6 без доступа к сети как исправить windows
  • Как найти сведения в едином государственном реестре
  • Как найти единорога в симс 3 код