conclusion

To weight method 10w data takes ms Complex data deduplication effect
Double loop 3139 Common types Except NaN, reference data types cannot
Array.prototype.indexOf() 2784 Common types Except NaN, reference data types cannot
Array.prototype.sort() 53 Common types Except NaN, reference data types cannot
Array.prototype.includes() 3018 Sorting result is wrong, adjacent judgment effect is not good
Array.prototype.reduce() 6 Normal data types work, but reference data types do not
Object key-value pairs (normal data type + special data) 60 Sorting result is wrong, adjacent judgment effect is not good
Object key-value pairs (complex objects) 77 To restore the correct
Map 9 Normal data types work, but reference data types do not
set 4 Normal data types work, but reference data types do not

The specific use depends on the situation

The name of the includes Map Set Object attribute distinguishes NaN

The test data

  • 10 w data
const arr = [];
// Generate random numbers between [0, 100000]
for (let i = 0; i < 100000; i++) {
  arr.push(0 + Math.floor((100000 - 0 + 1) * Math.random()))
}
Copy the code
  • Complex data
const arr = [1.1.'1'.'1'.0.0.'0'.'0'.undefined.undefined.null.null.NaN.NaN, {}, {}, [], [], /a/, /a/];
Copy the code

Double loop

Array.prototype.unique = function () {
  const newArray = [];
  for (let i = 0; i < this.length; i++) {
    for (let j = i + 1; j < this.length; j++) {
      if (this[i] === this[j]) {
        j = ++i;
      }
    }
    newArray.push(this[i]);
  }
  return newArray;
}
Copy the code
  • 10W array time: 3139.086181640625ms
  • Complex case results: NaN Object Array reguls are indistinguishable, and congruence is indistinguishable between reference data types and nans

Array.prototype.indexOf()

If the index is not the first one, it is a duplicate.

Array.prototype.unique = function () {
  const newArray = [];
  this.forEach(item= > {
    if (newArray.indexOf(item) === - 1) { newArray.push(item); }});return newArray;
}
Copy the code
  • 10W array time: 2784.8837890625ms
  • Complication result: Same as above, congruence does not distinguish between reference data types and NaN

Array.prototype.sort()

Sort the array first, then compare the elements.

Array.prototype.unique = function () {
  const newArray = [];
  this.sort();
  for (let i = 0; i < this.length; i++) {
    if (this[i] ! == newArray[newArray.length -1]) {
      newArray.push(this[i]); }}return newArray;
}
Copy the code
  • 10W array time: 53.389892578125ms
  • Complex data results: Sorting problems, and congruence cannot determine reference data types and nans

Array.prototype.includes()

Syntax: arr.includes(valueToFind[, fromIndex])

Array.prototype.unique = function () {
  const newArray = [];
  this.forEach(item= > {
    if (!newArray.includes(item)) {
      newArray.push(item);
    }
  });
  return newArray;
}
Copy the code
  • 10W Data time: 3018.489013671875ms
  • Complex data effects: All underlying data types can be distinguished, but reference types cannot.

polyfill

f (!Array.prototype.includes) {
  Object.defineProperty(Array.prototype, 'includes', {
    value: function(valueToFind, fromIndex) {

      if (this= =null) {
        throw new TypeError('"this" is null or not defined');
      }

      // 1. Let O be ? ToObject(this value).
      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);

      function sameValueZero(x, y) {
        return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
      }

      // 7. Repeat, while k < len
      while (k < len) {
        // a. Let elementK be the result of ? Get(O, ! ToString(k)).
        // b. If SameValueZero(valueToFind, elementK) is true, return true.
        if (sameValueZero(o[k], valueToFind)) {
          return true;
        }
        // c. Increase k by 1.
        k++;
      }

      // 8. Return false
      return false; }}); }Copy the code

Array.prototype.reduce()

Array.prototype.unique = function () {
  return this.sort().reduce((init, current) = > {
    if(init.length === 0 || init[init.length - 1] !== current){
      init.push(current);
    }
    returninit; } []); }Copy the code
  • 10W Data time: 6ms
  • Complex data effects: Sorting is wrong in the first place

Object key-value pairs

Basic idea: the use of the object’s key can not be repeated characteristics to carry out the weight.

Note:

  1. Can’t distinguish between the same value as an implicit type converted to a string, such as 1 and ‘1’
  2. Unable to handle complex data types such as objects (because objects become object objects as keys)
  3. Special data, such as ‘proto’, because the object’s proto property cannot be overridden

Solving problems (1,3)

Array.prototype.unique = function () {
  const newArray = [];
  const tmp = {};
  for (let i = 0; i < this.length; i++) {
    if(! tmp[typeof this[i] + this[i]]) {
      tmp[typeof this[i] + this[i]] = 1;
      newArray.push(this[i]); }}return newArray;
}
Copy the code
  • 10W data time: 60.39306640625ms
  • Complex data effect: This effect is better because the key value is type + string, and the same content is converted to string by different references.

TMP:

Problem Solving (2)

Array.prototype.unique = function () {
  const newArray = [];
  const tmp = {};
  for (let i = 0; i < this.length; i++) {
    // serialize with json.stringify ()
    if(! tmp[typeof this[i] + JSON.stringify(this[i])]) {
      // Use the serialized object as a key
      tmp[typeof this[i] + JSON.stringify(this[i])] = 1;
      newArray.push(this[i]); }}return newArray;
}
Copy the code

tmp:

  • 10W data time: 77.2470703125ms
  • Complex data effect: When an object is serialized, the result of the regular expression is {}, which is the same as the empty object.

Map

The key comparison is based on the SameValueZero algorithm: NaN is equal to NaN, and the remaining values are equal based on the result of the === operator.

Array.prototype.unique = function () {
  const tmp = new Map(a);return this.filter(item= > {
    return! tmp.has(item) && tmp.set(item,1); })}Copy the code
  • 10W data time: 9.539794921875ms
  • Complex data effects: Normal data types work, complex data types do not

Set

Nans in a set are treated as the same value.

Array.prototype.unique = function () {
  return [...new Set(this)];
}
Copy the code
  • 10W data time: 4.939208984375ms
  • Data deduplication effect: Normal data types work, complex data types don’t