preface

Array de-weight, this is an old meme… Today I took it out again… Let’s consider a more comprehensive implementation of array de-duplication, such as NaN,undefined,{}; This involves a lot of knowledge points, do not believe to follow a wave; Browser compatibility issues are not considered here, as ES5&6 is involved

Implementation of

Basic version

Contains only numbers that can be directly compared

The test array

[1, 1, ‘a’, ‘ ‘, ‘e’, ‘e’, true, ‘true, true, false, false,’ false ‘, undefined, “undefined”, undefined, null, “null”, null]

  • ES5The almightyformethods
function uniqueUseFor(array) {
  var temp = []; // a temporary array

  // Iterate over the current array
  for (var i = 0, j = array.length; i < j; i++) {
    // If the new array does not have the value, the new array is pushed
    temp.indexOf(array[i]) === - 1 ? temp.push(array[i]) : ' ';
  }
  return temp;
}

// result: [1, "", "e", true, "true", false, "false", undefined, "undefined", "null", null]
Copy the code
  • ES5The built-inforEachmethods
function uniqueUseForEach(array) {
  // The incoming value must exist, and the array must be returned if the length is less than or equal to 1
  if (array && array.length <= 1) {
    return array;
  } else {
    var temp = []; // a temporary array
    // Iterate over the current array
    array.forEach(function (value, index) {
      temp.indexOf(value) == - 1 ? temp.push(value) : ' ';
    })
    returntemp; }}// result: [1, "", "e", true, "true", false, "false", undefined, "undefined", "null", null]
Copy the code
  • The built-in [ES6]for-ofmethods
function uniqueUseForOf(array) {
  const temp = []; // a temporary array
  // The incoming value must exist, and the array must be returned if the length is less than or equal to 1
  if (array && array.length <= 1) {
    return array;
  } else {
    // Iterate over the current array
    for (let x of array) {
      temp.indexOf(x) === - 1 ? temp.push(x) : ' '; }}return temp;
}
// result: [1, "", "e", true, "true", false, "false", undefined, "undefined", "null", null]
Copy the code

premium

Contains NaN, undefined, null

The test array

[1, 1, ‘true, true, true, 5,’ F ‘, false, undefined, null, null, and undefined, NaN, 0, 1, ‘a’, ‘a’, NaN, ‘NaN’]

knowledge

  • NaN has two general determination methods and one of array determination methods:

  • One is absolutely not equal to (===) itself

  • One is isNaN() for ES6

  • Array.prototype.includes()

function uniqueUseNotAllEqual(array) {

  var temp = [], // a temporary array
      mark = true; / / logo

  // Iterate over the current array
  for (var i = 0, j = array.length; i < j; i++) {
    // The identifier bit is used to determine if NaN exists and is retained in the new array for the first time
    // Then the flag position is changed to false so that the array is not pushed when it is found again
    if(array[i] ! == array[i]) {// isNaN can also be used to determine the inequality of [ES6]
      mark && temp.indexOf(array[i]) == - 1 ? temp.push(array[i]) : ' ';
      mark = false;

    } else
      temp.indexOf(array[i]) == - 1 ? temp.push(array[i]) : ' ';

  }
  return temp;
}

// result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
Copy the code
  • Built-in [ES6]Array.prototype.includes()solution
function uniqueCompareUseIncludes(array) {
  // The incoming value must exist, and the array must be returned if the length is less than or equal to 1
  if (array && array.length <= 1) {
    return array;
  } else {
    let temp = []; // a temporary array
    // Iterate over the current array
    for (let x of array) {
      The // includes() method is used to determine whether the current array contains a specified value and returns true if so, false otherwise.
      temp.includes(x) ? ' ': temp.push(x) ;
    }
    returntemp; }}// result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]
Copy the code
  • [ES6] Array.fromOr extend the operator [.] combinationSetsolution

knowledge

  • SetThe value of is unique and internally automatic= = =Iterable, a little bit specialNaNAlthough this product has incomplete characteristics, inSetThey think it’s the same, so there can only be one
  • Array.fromand.An iterable object like an array can be converted to a standard array
// array. from + Set
Array.from(new Set([1.1.'true'.true.true.5.'F'.false.undefined.null.null.undefined.NaN.0.1.'a'.'a'.NaN.'NaN']))
// resule: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]


/ /... + Set method
[...new Set([1.1.'true'.true.true.5.'F'.false.undefined.null.null.undefined.NaN.0.1.'a'.'a'.NaN.'NaN']]//result: [1, "true", true, 5, "F", false, undefined, null, NaN, 0, "a", "NaN"]

Copy the code

Higher-order version

Contains {}, NaN, undefined, null

The test array

[1, 1, ‘true, true, true, 5,’ F ‘, false, undefined, null, null, and undefined, NaN, {}, {}, ‘{}’, 0, 1, ‘a’, ‘a’, NaN]

knowledge

  • Json.stringify ({}) == ‘{}’

  • A perfect solution is to judge by toString of for in combined with prototype chain

  • Es5for-in + Call + FOR solution

function uniqueUseForIn(array) {
  var temp = [];
  var emptyObjectMark = true; / / logo
  var NaNObjectMark = true; / / logo
  // Empty object
  function isEmptyObject(object) {
    if (Object.prototype.toString.call(object) === "[object Object]") {
      for (var i in object) {
        // If an attribute or method exists, it is not an empty object
        return false
      }
      return true;
    } else {
      return false; }}// The incoming value must exist, and the array must be returned if the length is less than or equal to 1
  if (array && array.length <= 1) {
    return array;
  } else {
    // Iterate over the current array
    for (var i = 0, j = array.length; i < j; i++) {
      // The identifier bit is used to determine the existence of NaN and empty objects, and is retained in the new array the first time it is found
      // Then the flag position is changed to false so that the array is not pushed when it is found again
      if (isEmptyObject(array[i])) {
        emptyObjectMark && temp.indexOf(array[i]) == - 1 ? temp.push(array[i]) : ' ';
        emptyObjectMark = false;
      } else if(array[i] ! == array[i]) { NaNObjectMark && temp.indexOf(array[i]) ==- 1 ? temp.push(array[i]) : ' ';
        NaNObjectMark = false;
      } else
        temp.indexOf(array[i]) == - 1 ? temp.push(array[i]) : ' ';

    }
    returntemp; }}/ / result: [1, "true", true, 5, "F", false, undefined, null, NaN, Object, "{}" 0, "a"]
Copy the code

Development version

Multidimensional array flattening and then de-weighting;

Response:

Message board friends said to heavy depth is not enough. 2017/5/12

The test array

[1, 1, [[‘ true, true, true, [5, ‘F’], false], undefined], null, null, / undefined, NaN, {}, {}, ‘{}’, 0, 1, ‘a’, ‘a’, NaN]

knowledge

  • Array flattening is implemented recursively
  • The code also takes into account default parameters to prevent errors when no parameters are passed
  • ES5for-in + call + for+ Recursive flattening scheme
function uniqueArrayWithFlattern(array) {
  var _array = array || []; // Save the parameter
  // Empty object
  function isEmptyObject(object) {
    if (Object.prototype.toString.call(object) === "[object Object]") {
      for (var i in object) {
        // If an attribute or method exists, it is not an empty object
        return false
      }
      return true;
    } else {
      return false; }}// Traverses the query to determine, flattening the array
  function forArrayFlattern(arr) {

    for (var m = 0, n = arr.length; m < n; m++) {
      if (Array.isArray(arr[m])) {
        var _tempSpliceArr = _array.splice(m, 1) [0];
        _array = _array.concat(_tempSpliceArr);
        returnforArrayFlattern(_array); }}return uniqueArr(_array);
  }


  // The incoming value must exist, and the array must be returned if the length is less than or equal to 1
  if (_array && _array.length <= 1) {
    return _array
  } else {
    if (Array.isArray(_array)) {
      return forArrayFlattern(_array)
    } else {
      return_array; }}// Array decrement
  function uniqueArr(_array) {
    var temp = [];
    var emptyObjectMark = true; / / logo
    var NaNObjectMark = true; / / logo
    console.log(_array.length)
    // Iterate over the current array
    for (var a = 0, b = _array.length; a < b; a++) {
      // The identifier bit is used to determine the existence of NaN and empty objects, and is retained in the new array the first time it is found
      // Then the flag position is changed to false so that the array is not pushed when it is found again

      console.log(_array[a]);
      if (isEmptyObject(_array[a])) {
        emptyObjectMark && temp.indexOf(_array[a]) == - 1 ? temp.push(_array[a]) : ' ';
        emptyObjectMark = false;
      } else if(_array[a] ! == _array[a]) { NaNObjectMark && temp.indexOf(_array[a]) ==- 1 ? temp.push(_array[a]) : ' ';
        NaNObjectMark = false;
      } else {
        temp.indexOf(_array[a]) === - 1 ? temp.push(_array[a]) : ' '; }}console.log(temp);
    returntemp; }}/ / the result: [1, null, the Object, "{}" 0, "a", NaN, undefined, "true", true, false, 5, "F"]
// In ES6, the code should be a little more compact
Copy the code

conclusion

I believe you guys understand this, all kinds of interview pattern array to heavy requirements for you are not very pit;