超级牛逼的答案:一行搞定
return [...new Set(puzzles.flat())]
[...new Set(puzzles.flat())]
的核心思想是:- 展平:将多维数组转为一维。puzzles.flat()
- 去重:利用 Set 的唯一性特性自动过滤重复元素。new Set()
- 转数组:通过展开运算符返回最终结果。 ...
- 这种写法简洁高效,是现代 JavaScript 中处理数组去重的常见模式。
- 也可以写成
return Array.from(new Set(puzzles.flat()))
如何想到题目是要处理数组去重的呢?
当然是审题!
暗含着咱们只要去重,不用管数量
在 JavaScript 中,数组去重是常见的操作,以下是几种常见且高效的实现方法及原理分析:
1. 使用 Set
数据结构(ES6)
原理:Set
是 ES6 引入的内置对象,其成员唯一,自动去重。
写法:
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = [...new Set(array)]; // 或 Array.from(new Set(array));
console.log(uniqueArray); // [1, 2, 3, 4, 5]
优点:
- 简洁高效:时间复杂度为
O(n)
,适合大数据量。 - 保持插入顺序:ES2019 后
Set
保留元素插入顺序。 缺点: - 不支持旧浏览器:需 polyfill 或兼容处理。
2. 使用 filter
+ indexOf
/includes
原理:遍历数组,保留首次出现的元素,后续重复元素被过滤。
写法:
const array = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = array.filter((item, index) => {
return array.indexOf(item) === index; // 或 array.indexOf(item, index + 1) === -1
});
// 或使用 includes:
const uniqueArray2 = array.filter((item, index, self) => {
return self.indexOf(item) === index;
});
console.log(uniqueArray); // [1, 2, 3, 4, 5]
优点:
- 兼容性好:支持 ES5 及以上。
- 简单易懂。
- 缺点:时间复杂度高:
O(n²)
(indexOf
内部遍历),大数据量时效率低。
3. 使用 reduce
方法
原理:通过累加器(accumulator
)收集唯一元素。
本题写法:
function collectPuzzle(...puzzles) {
let arr =puzzles.flat()
return arr.reduce((acc,cur)=>{
if(!acc.includes(cur)){
acc.push(cur)
}
return acc
},[])
}
优点:
- 可读性强:逻辑清晰,适合复杂场景。
- 缺点:时间复杂度:
O(n²)
(includes
内部遍历)。
疑问:
1.let可以改为const吗?
在JavaScript中,let
和 const
都用于声明变量,但它们之间有一些关键的区别:
let
声明的变量可以被重新赋值。const
声明的变量一旦被初始化后就不能被重新赋值。
对于这段代码,我们可以看到 arr
是一个数组,并且它在后续的代码中会被修改(通过 reduce
方法)。因此,使用 let
是合适的,因为数组 arr
会被修改。
2.第一个return为什么不能删?
return arr.reduce(...)
它的作用是将 reduce
的结果(一个去重后的数组)返回给调用者。
3.第二个return为什么不能删?
reduce
的回调函数必须返回累积器的值(acc
),以便在下一次迭代中继续使用。
4. 对象数组去重
场景:当数组元素是对象时,需根据对象属性去重。
(使用 Map):
const uniqueArray = [...new Map(array.map(item => [item.id, item])).values()];
注意事项:
- 需指定唯一属性(如
id
),否则默认比较对象引用。
总结与选择建议
方法 | 时间复杂度 | 适用场景 | 兼容性 |
---|---|---|---|
Set | O(n) | 基础类型,现代浏览器 | 需 ES6 支持 |
filter + indexOf | O(n²) | 小数据量,兼容性要求高 | 全部浏览器 |
reduce | O(n²) | 需要可读性,逻辑扩展性强 | 全部浏览器 |
双重循环 | O(n²) | 简单场景,需原地修改 | 全部浏览器 |
对象数组(Map/属性) | O(n) | 对象去重,需指定唯一属性 | 需 ES6 支持 |
注意事项
- 元素类型:
- 基础类型:直接比较值(如
number
,string
)。 - 对象/数组:需用
JSON.stringify
或自定义比较函数。
- 基础类型:直接比较值(如
- 性能:
- 大数据量优先选
Set
或哈希表方法。 - 对象数组需根据唯一属性去重。
- 大数据量优先选
- 顺序保留:
- 所有方法均保留首次出现的元素顺序。
根据实际需求选择合适的方法,例如:
- 现代项目推荐
Set
; - 兼容旧浏览器用
filter + indexOf
; - 对象数组用
Map
或自定义哈希。
相关类似的题目