zl程序教程

您现在的位置是:首页 >  其它

当前栏目

_.unionWith([arrays], [comparator])

Arrays _. Comparator
2023-09-11 14:15:02 时间

51

_.unionWith([arrays], [comparator])
_.unionWith类似union方法,多传递一个comparator自定义比较方法

参数

[arrays] (...Array): 需要处理的多个数组

[comparator] (Function): 比较元素是否相等的自定义比较器

返回值

(Array): 返回连起来的去重后的数组

例子

var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
 
_.unionWith(objects, others, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]

源代码:

import baseFlatten from './.internal/baseFlatten.js'
import baseUniq from './.internal/baseUniq.js'
import isArrayLikeObject from './isArrayLikeObject.js'
import last from './last.js'

/**
 * This method is like `union` except that it accepts `comparator` which
 * is invoked to compare elements of `arrays`. Result values are chosen from
 * the first array in which the value occurs. The comparator is invoked
 * with two arguments: (arrVal, othVal).
 *
 * @since 4.0.0
 * @category Array
 * @param {...Array} [arrays] The arrays to inspect.
 * @param {Function} [comparator] The comparator invoked per element.
 * @returns {Array} Returns the new array of combined values.
 * @see difference, union, unionBy, without, xor, xorBy
 * @example
 *
 * const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
 * const others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]
 *
 * unionWith(objects, others, isEqual)
 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
 */
//类似union方法,多传递一个comparator自定义比较方法
function unionWith(...arrays) {
  let comparator = last(arrays)//最后一个参数是comparator
  comparator = typeof comparator == 'function' ? comparator : undefined//comparator不是函数就赋值为undefined
  return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator)
  //调用baseUniq处理
}

export default unionWith

baseUniq

import SetCache from './SetCache.js'
import arrayIncludes from './arrayIncludes.js'//判断数组是否包含给定值
import arrayIncludesWith from './arrayIncludesWith.js'//判断数组是否包含给定值,区别是它的comparator需要作为参数传入
import cacheHas from './cacheHas.js'
import createSet from './createSet.js'
import setToArray from './setToArray.js'

/** Used as the size to enable large array optimizations. */
const LARGE_ARRAY_SIZE = 200

/**
 * The base implementation of `uniqBy`.
 *
 * @private
 * @param {Array} array The array to inspect.
 * @param {Function} [iteratee] The iteratee invoked per element.
 * @param {Function} [comparator] The comparator invoked per element.
 * @returns {Array} Returns the new duplicate free array.
 */
//uniqBy的基础实现,数组去重
function baseUniq(array, iteratee, comparator) {
  let index = -1//循环索引
  let includes = arrayIncludes//类似数组的includes方法,判断数组是否包含给定值
  let isCommon = true//有没有自定义比较器或者有没有开启缓存的标记

  const { length } = array//数组长度
  const result = []//结果数组
  let seen = result//临时数组,用来存入不重复的数组元素值

  if (comparator) {//如果传递了自定义比较器,incledes方法就用arrayIncludesWith
    isCommon = false
    includes = arrayIncludesWith
  }
  else if (length >= LARGE_ARRAY_SIZE) {//如果数组长度超过200,就设置缓存
    const set = iteratee ? null : createSet(array)//如果没有iteratee和comparator,就直接使用ES6的set类型去重
    if (set) {//如果可以用set类型去重,直接新建set对象然后再转换成数组后返回结果
      return setToArray(set)
    }
    isCommon = false//否则开启数组缓存
    includes = cacheHas
    seen = new SetCache
  }
  else {//如果没有自定义比较器,数组长度也没有超过200
    seen = iteratee ? [] : result
  }
  outer:
  while (++index < length) {//遍历数组
    let value = array[index]//当前元素
    const computed = iteratee ? iteratee(value) : value//iteratee处理后的当前元素

    value = (comparator || value !== 0) ? value : 0//如果没有传递comparator,将-0变为0
    if (isCommon && computed === computed) {//如果没有传递自定义比较器,或者没有开启缓存,并且computed不是NaN
      let seenIndex = seen.length//seen数组的长度
      while (seenIndex--) {//遍历seen数组,如果有和当前值一样的,就跳出本次循环直接进行下一次
        if (seen[seenIndex] === computed) {
          continue outer
        }
      }
      if (iteratee) {//如果有iteratee参数,seen结尾插入当前不重复的元素
        seen.push(computed)
      }
      result.push(value)//结果数组结尾插入当前不重复的元素
    }
    else if (!includes(seen, computed, comparator)) {//如果有自定义比较器或者开启了缓存,并且seen中没有当前元素
      if (seen !== result) {//开启缓存的情况seen数组要插入新值
        seen.push(computed)
      }
      result.push(value)//结果数组插入新值
    }
  }
  return result
}

export default baseUniq