标准答案
- 数组去重:基本值去重可以用 [...new Set(arr)]。对象数组去重通常要先确定 key,例如 id,再用 Map 记录 key 到对象。
- 数组扁平化:运行环境支持时优先用 arr.flat(depth)。手写时可以递归处理,也可以用栈避免深层递归导致调用栈溢出。
- 数组分组:可以用 reduce 构造普通对象,也可以用 Map。分组 key 可能不是字符串或需要保留插入顺序时,Map 更合适。
- 方案选择要看数据结构。Set 只按值相等或引用相等去重,不能自动理解两个对象的业务 id;flat 只解决数组层级,不负责去重;groupBy 只负责归类,不负责排序和聚合。
题目解析
基本值去重和对象去重的判断标准不同。Set 能处理 1、1、NaN 这类值,但两个内容相同的对象只要不是同一引用,就会被当作不同元素。
扁平化要说明 depth。flat(1) 只展开一层,flat(Infinity) 可以展开所有层;手写递归时要考虑深度过大和稀疏数组等边界。
如果运行环境支持 Object.groupBy 或 Map.groupBy,可以作为补充。面试复述时仍应能说出 reduce 或 Map 的基础实现思路,因为兼容性和构建环境可能不同。
代码示例
下面示例分别处理对象数组去重、指定深度扁平化和按字段分组。
JavaScript
function uniqueBy(list, getKey) {
const map = new Map()
list.forEach((item) => {
map.set(getKey(item), item)
})
return [...map.values()]
}
function flatten(list, depth = 1) {
if (depth <= 0) return list.slice()
return list.reduce((result, item) => {
if (Array.isArray(item)) {
result.push(...flatten(item, depth - 1))
} else {
result.push(item)
}
return result
}, [])
}
function groupBy(list, getKey) {
return list.reduce((map, item) => {
const key = getKey(item)
const group = map.get(key) || []
group.push(item)
map.set(key, group)
return map
}, new Map())
}常见误区
- 用 Set 给对象数组去重,结果只去掉同一引用对象。
- 递归 flat 不处理 depth 或深层数组。
- 分组时用普通对象但没有考虑 key 为 __proto__ 等特殊情况。