如何优化按owner分组生成对象属性数组的代码实现?
优化数组与对象匹配的实现方案
问题背景
现有如下数组和对象,需要将它们匹配得到目标结果:
原始数据
const items = [ { key: 1, name: 'A', owner: 'Alex', }, { key: 2, name: 'B', owner: 'Barb', }, { key: 3, name: 'C', owner: 'John', }, { key: 4, name: 'D', owner: 'Barb', }, { key: 5, name: 'E', owner: 'Alex', }, ]; const owners = { 'Alex': { 1: [], 5: [] }, 'John': { 3: [], }, 'Barb': { 2: [], 4: [] }, }
期望结果
const ownersWithName = { 'Alex': [{ key: 1, name: 'A', }, { key: 5, name: 'E' }], 'Barb': [{ key: 2, name: 'B', }, { key: 4, name: 'D' }], 'John': [{ key: 3, name: 'C', }, ], }
原始实现
当前实现可正常运行,但代码较为冗长:
function matchOwners (items, owners) { const ownersWithName = {}; for (const item of items) { if (owners[item.owner]) { if (ownersWithName[item.owner]) { ownersWithName[item.owner] = [ ...ownersWithName[item.owner], item]; } else { ownersWithName[item.owner] = [item]; } } } return ownersWithName; }
尝试直接使用扩展运算符时,因数组未初始化会报错ownersWithName[item.owner] is not iterable,希望找到更简洁的实现方式。
优化方案
方案一:用逻辑或简化数组初始化
通过|| []确保扩展运算符始终有可迭代的数组,去掉嵌套判断:
function matchOwners(items, owners) { const ownersWithName = {}; for (const item of items) { if (owners[item.owner]) { // 若属性不存在则用空数组初始化,再扩展添加当前item ownersWithName[item.owner] = [...(ownersWithName[item.owner] || []), item]; } } return ownersWithName; }
方案二:使用reduce函数实现函数式聚合
利用数组的reduce方法一次性完成聚合,代码更简洁紧凑:
function matchOwners(items, owners) { return items.reduce((acc, item) => { if (owners[item.owner]) { acc[item.owner] = [...(acc[item.owner] || []), item]; } return acc; }, {}); }
方案三:基于原owners结构初始化(更严谨)
如果需要严格只保留原owners中存在的所有者(即使items里有额外owner也忽略),可以先初始化结果对象的结构,再填充数据:
function matchOwners(items, owners) { // 先基于owners的键初始化空数组 const ownersWithName = Object.fromEntries( Object.keys(owners).map(owner => [owner, []]) ); for (const item of items) { if (ownersWithName[item.owner]) { // 直接push,比扩展运算符性能更好(避免每次创建新数组) ownersWithName[item.owner].push(item); } } return ownersWithName; }
这个方案的优势是:
- 确保结果对象的键完全和原owners一致
- 使用
push比扩展运算符更高效,尤其是数据量较大时
内容的提问来源于stack exchange,提问作者asantiagot
相关产品推荐
相关产品推荐

