A way to get rid of weight

Deduplication is a hot issue often encountered in the development, but the current situation encountered in the project is the background interface using SQL deduplication, simple and efficient, basically do not let the front-end processing of deduplication.

Of course, this is not to say that the front end to heavy is not necessary, still need to be skilled in use. The following are some common methods of array de-duplication.

1. HasOwnProperty () + filter + Object attributes must be unique

All of them are gone

  1. hasOwnProperty()Method returns a Boolean that determines whether the object contains a specific (non-inherited) property of itself.

function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}let obj = {}
  arr.filter(item= > obj.hasOwnProperty(typeOf item + item) ? false : obj[typeOf item + item] = true)}Copy the code

2. ES6 set + destruct assignment (common)

The object is not deduplicated

  1. The simplest, most common method, there is no one.

  2. One of the biggest features of a Set is that data does not duplicate.

  3. The Set function can be initialized by taking an array (or array-like object) as an argument.


function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}return [...new Set(arr)]
}

Copy the code

3. ES6 set + Array.from

The object is not deduplicated

The array.from () method creates a new, shallow-copy Array instance from an array-like or iterable.


function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}return Array.from(new Set(arr))
}

Copy the code

4. includes

The object is not deduplicated

  1. The includes() method determines whether the array contains a specified value, returning true if it does and false otherwise.

  2. [NaN]. Includes (NaN) is true


function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}let res = []
  arr.forEach(item= > {
    if(! res.includes(item)) { res.push(item) } })return res
}

Copy the code

5. reduce + includes

The object is not deduplicated

  1. The reduce() method performs a reducer function (in ascending order) that you provide on each element in the array, summarizing its results into a single return value.

  2. Reduce () takes two arguments: a callback function and an initial value passed to total

  3. [NaN]. Includes (NaN) is true


function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}return arr.reduce((total, cur) = > total.includes(cur) ? pre : [...pre, cur], [])
}

Copy the code

6. Use “for” to nest “for” and then splice to de-duplicate (most commonly used in ES5)

NaN and object are not de-weighted


function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}for (let i = 0; i < arr.length - 1; i++) {
    for (let j = arr.length; j > i; j--) {
      if (arr[i] === arr[j]) arr.splice(j, 1)}}return arr
}

Copy the code

J is better to look forward from the end, because the index of the following element splice is one digit forward.

7. indexOf

NaN and object are not de-weighted


function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}let res = []
  arr.forEach(item= > {
    if (res,indexOf(item) === -1) {
      res.push(item)
    }
  })
  return res
}

Copy the code

8. indexOf + filter

NaN and object are not de-weighted

  1. filter()Method creates a new array containing all the elements of the tests implemented through the provided function.

function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}return arr.filter((item, index, arr) = > arr.indexOf(item) === index)
}

Copy the code

Unique ([NaN, NaN]) returns [] because arr.indexof (NaN) is -1

9. sort()

NaN and object are not de-weighted

  1. Use sort() sorting method, and then traverse and compare adjacent elements according to the sorted result.

  2. The sort() method sorts the elements of an array using an in-place algorithm. Array.prototype.sort()


function unique(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')
  }

  arr = arr.sort()
  let res = arr[0] && [arr[0]]
  for (let i = 1; i < arr.length; i++) {
    if(arr[i] ! == arr[i-1]) {
      res.push(arr[i])
    }
  }
  return res
}

Copy the code

conclusion

According to the results of the weight reduction

  1. All go heavy:

    • 1. HasOwnProperty () + filter + Object attributes must be unique
  2. The object is not deduplicated

    • 2.ES6 set + destruct assignment
    • 3.ES6 set and array. from are deleted
    • 4.includes
    • 5.reduce + includes
  3. NaN and object are not de-weighted

    • 6. Use “for” to nest “for” and then splice to de-duplicate (most commonly used in ES5)
    • 7.indexOf
    • 8.indexOf + filter
    • 9.sort()

Look at it in terms of de-weighting

With the exception of 6. Use for to nest for, and then splice (most commonly used in ES5) to modify the original array, all create a new array, then append the non-repeating elements to the new array by various methods, and return the new array.

Flattening method

Array flattening converts a nested array(which can be any number of layers) into a one-layer array, for example, converting the array [1,[2,[3,[4,5]]]] to [1,2,3,4,5].

The most straightforward way to flatten an Array is to use the array.prototype.flat () method (poor compatibility), followed by recursively levelling the Array at each level by iterating through a set of elements.

1. ES6 flat

  1. Syntax: res = arr.flat([depth])

  2. Description:

    • Depth specifies the structural depth to extract the nested array. The default value is 1.
    • parameterdepth <= 0, returns the original array;
    • Parameters as the depthInfinityKeyword, no matter how many layers are nested, will be converted to a one-dimensional array,
    • flat()The method removes an empty item from the array, which is skipped if there is a space in the original array.

2. reduce

  1. Iterate over each item of the group, recursively if the value is array, otherwise concat.

function flatten(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}return arr.reduce((total, cur) = > total.concat(Array.isArray(cur) ? flatten(cur) : cur), [])
}

Copy the code

3. toString (join) & split

  1. If the array’s entries are all numbers, convert the array to a string using join(), toString(), which strips out [], and then calls split() to convert the array to an array.

    Each item in the array performs toString(), so the number becomes a string.


function flatten(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}return arr.toString().split(', ').map(item= > +item)

  ---------------------------------------------------

  return arr.join(', ').split(', ').map(item= > +item)
}

Copy the code

Strings do not need map().

4. Recursion (or stack)

As with Reduce, reduce is simpler than this.


function flatten(arr) {
  if (!Array.isArray(arr)) {
    throw new TypeError('arr must be an Array')}let res = []
arr.forEach(item= > res.concat(Array.isArray(item) ? flatten(item) : item))
return res
}

Copy the code

conclusion

Other than flat(), the other methods are to recursively level the array at each level by iterating through the array of elements.

Tree flat

1. Recursive implementation

Walk through the tree, add each item to the result set, recurse if there are children and the length is not zero.

Here we need to remove the children attribute from each node with a deconstructive assignment.

function treeToArray(tree) {
  let res = []
  for (const item of tree) {
    const{ children, ... i } = itemif (children && children.length) {
      res = res.concat(treeToArray(children))
    }
    res.push(i)
  }
  return res
}
Copy the code

2. reduce

The idea of the same recursive implementation, a bit more concise

function treeToArray(tree) {
  return tree.reduce((res, item) = > {
    const{ children, ... i } = itemreturn res.concat(i, children && children.length ? treeToArray(children) : [])
  }, [])
}
Copy the code

reference

  1. JavaScript Array deduplicating (12 ways, the most complete ever)
  2. There are seven ways to implement array de-duplication
  3. Some methods of JS array flattening (7-8 kinds)