lodash数组拼接:concat与union合并数组

lodash数组拼接:concat与union合并数组

【免费下载链接】lodash A modern JavaScript utility library delivering modularity, performance, & extras. 【免费下载链接】lodash 项目地址: https://gitcode.com/gh_mirrors/lo/lodash

在日常开发中,数组拼接是常见的操作,但不同的合并方式会产生截然不同的结果。你是否遇到过合并数组时出现重复元素的问题?或者需要深度合并多层数组却不知从何下手?本文将详细对比lodash中的concatunion两个数组合并方法,帮助你在不同场景下选择最合适的工具。读完本文后,你将能够:掌握两种合并方法的核心差异、解决重复元素问题、处理特殊数据类型合并,并通过实际案例优化代码性能。

核心方法对比

concat方法:灵活的浅合并工具

concat方法是lodash中最基础的数组合并工具,它能够将多个数组或值拼接成一个新数组。与原生JavaScript的Array.prototype.concat相比,lodash的concat提供了更好的兼容性和一致性。

基础用法

// 简单数组拼接
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const result = _.concat(arr1, arr2);
// 结果: [1, 2, 3, 4, 5, 6]

// 混合值类型拼接
const result = _.concat([1], 2, [3], [[4]]);
// 结果: [1, 2, 3, [4]]

test/concat.spec.js的测试用例可以看出,concat具有以下特性:

  • 不会修改原数组,而是返回一个全新的数组
  • 能够处理非数组值,会将其作为单个元素添加
  • 对稀疏数组(sparse array)会被视为密集数组处理
  • 只进行浅层次的合并,不会递归展开嵌套数组

union方法:自动去重的合并工具

union方法则专注于合并多个数组并自动去除重复元素。它内部使用了baseUniq方法来确保结果数组中的元素唯一性。

源码解析

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

function union(...arrays: any[]) {
    return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
}

export default union;

src/union.ts中的实现展示了union的工作流程:

  1. 使用baseFlatten将输入的多个数组展平一层
  2. 通过baseUniq方法去除重复元素
  3. 只处理类数组对象(array-like object)

基础用法

// 基本去重合并
const arr1 = [1, 2, 3];
const arr2 = [3, 4, 5];
const result = _.union(arr1, arr2);
// 结果: [1, 2, 3, 4, 5]

// 多数组合并
const result = _.union([1, 2], [2, 3], [3, 4]);
// 结果: [1, 2, 3, 4]

实战场景对比

场景一:保留所有元素(包括重复项)

当你需要合并数组并保留所有元素,包括重复项时,concat是理想选择:

// 合并购物车商品(允许重复商品)
const cart1 = ['apple', 'banana'];
const cart2 = ['banana', 'orange'];
const combinedCart = _.concat(cart1, cart2);
// 结果: ['apple', 'banana', 'banana', 'orange']

场景二:确保元素唯一性

当需要合并多个数组并自动去重时,union更适合:

// 合并用户标签并去重
const tags1 = ['frontend', 'javascript'];
const tags2 = ['javascript', 'lodash'];
const uniqueTags = _.union(tags1, tags2);
// 结果: ['frontend', 'javascript', 'lodash']

场景三:处理嵌套数组

concatunion都只会展平一层嵌套数组,对于深层嵌套需要配合其他方法:

// concat处理嵌套数组
const resultConcat = _.concat([1], [2, [3]], [[4]]);
// 结果: [1, 2, [3], [4]]

// union处理嵌套数组
const resultUnion = _.union([1, [2]], [[2], 3]);
// 结果: [1, [2], 3] (注意[2]被视为唯一元素)

如果需要深度展平数组,可以结合使用flatten方法:

// 深度展平后合并去重
const arr1 = [1, [2, [3]]];
const arr2 = [3, [4]];
const result = _.union(_.flattenDeep(arr1), _.flattenDeep(arr2));
// 结果: [1, 2, 3, 4]

性能对比与优化

在处理大型数组时,选择合适的方法对性能至关重要:

操作场景concatunion
简单合并快(O(n))较慢(O(n log n) 由于去重)
去重合并需要额外去重步骤内置去重功能
内存占用较高(需要存储唯一值索引)

优化建议

  • 当处理大型数组且不需要去重时,优先使用concat
  • 如需去重,unionconcat+uniq组合更高效
  • 对于嵌套数组,考虑使用unionByunionWith进行自定义去重

常见问题与解决方案

问题一:合并对象数组时的去重问题

union方法使用严格相等(===)比较元素,对于对象数组无法正确去重:

// 对象数组去重失败
const arr1 = [{ id: 1 }, { id: 2 }];
const arr2 = [{ id: 2 }, { id: 3 }];
const result = _.union(arr1, arr2);
// 结果: [{ id: 1 }, { id: 2 }, { id: 2 }, { id: 3 }]

解决方案:使用unionByunionWith

// 使用unionBy按id去重
const result = _.unionBy(arr1, arr2, 'id');
// 结果: [{ id: 1 }, { id: 2 }, { id: 3 }]

问题二:处理复杂数据类型

当需要合并包含null、undefined等特殊值的数组时:

// 包含特殊值的数组合并
const arr1 = [null, undefined, 0, false];
const arr2 = [undefined, null, true, 0];
const resultConcat = _.concat(arr1, arr2);
const resultUnion = _.union(arr1, arr2);

// concat结果: [null, undefined, 0, false, undefined, null, true, 0]
// union结果: [null, undefined, 0, false, true]

总结与最佳实践

方法选择指南

需求场景推荐方法时间复杂度
简单合并,保留重复项concatO(n)
合并并去重基本类型unionO(n log n)
按属性去重对象数组unionByO(n log n)
自定义规则去重unionWithO(n log n)
深度合并嵌套数组concat + flattenDeepO(n)

性能优化技巧

  1. 当处理大量数据时,考虑先合并再去重,而非多次调用union
  2. 对于已知不会有重复项的场景,优先使用concat
  3. 处理对象数组时,使用unionBy指定唯一键,避免全对象比较
  4. 对于大型数组,考虑分块处理以避免内存问题

掌握concatunion的使用场景和差异,能够帮助你在实际开发中写出更高效、更清晰的代码。根据具体需求选择合适的方法,既能保证功能正确性,又能优化性能。lodash还提供了unionByunionWith等变体方法,满足更复杂的合并需求,建议结合官方文档深入学习。

【免费下载链接】lodash A modern JavaScript utility library delivering modularity, performance, & extras. 【免费下载链接】lodash 项目地址: https://gitcode.com/gh_mirrors/lo/lodash

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值