实现按共享属性为产品分配groupId的TypeScript函数
需求概述
- 接收产品数组作为入参
- 返回新数组,每个产品对象新增
groupId属性 - 若多个产品在
groupIfIdentical指定的所有属性上值完全一致,则共享同一个groupId
给定函数骨架
function groupProductsBySharedAttributes( products: Product[], groupIfIdentical: (keyof Product)[], initialGroupId: string, ) { }
修正分组判断逻辑
首先注意到提供的productsAreIdentical函数存在逻辑缺陷:循环内仅检查第一个属性就返回true,无法完成所有指定属性的一致性验证。修正后的判断函数如下:
function productsAreIdentical( prod1: Product, prod2: Product, groupIfIdentical: (keyof Product)[], ) { for (const key of groupIfIdentical) { if (prod1[key] !== prod2[key]) { return false; } } return true; }
不过更高效的实现方式是通过属性组合生成唯一标识键来映射groupId,避免重复遍历比较,以下是完整的函数实现:
完整实现代码
// 定义Product基础类型(可根据实际业务扩展) type Product = Record<string, any>; function groupProductsBySharedAttributes( products: Product[], groupIfIdentical: (keyof Product)[], initialGroupId: string, ) { // 存储属性组合与groupId的映射关系 const attributeGroupMap = new Map<string, string>(); let currentGroupId = parseInt(initialGroupId, 10); return products.map(product => { // 生成当前产品指定属性的唯一标识键 const attributeKey = groupIfIdentical .map(key => `${key}:${product[key]}`) .join('|'); // 若该属性组合未分组,则分配新的groupId if (!attributeGroupMap.has(attributeKey)) { attributeGroupMap.set(attributeKey, currentGroupId.toString()); currentGroupId++; } // 返回新增groupId的新对象(不修改原产品对象) return { ...product, groupId: attributeGroupMap.get(attributeKey) }; }); }
实现细节说明
- 唯一键生成:将指定属性的键值对拼接成字符串(如
country:china|material:steel),作为分组的唯一标识 - 分组映射:用
Map存储属性组合与groupId的对应关系,避免重复计算分组 - groupId递增:将初始
groupId转为数字,每遇到新的属性组合就自增,保证分组ID唯一 - 纯函数设计:通过扩展运算符创建新对象,不会修改原产品数组的元素
示例验证
const prods = [ { country: 'china', material: 'steel', sku: 1453 }, { country: 'china', material: 'steel', sku: 4874 }, { country: 'japan', material: 'steel', sku: 4874 }, ]; const result = groupProductsBySharedAttributes(prods, ['country', 'material'], '1001'); console.log(result); /* 输出结果: [ { country: 'china', material: 'steel', sku: 1453, groupId: '1001' }, { country: 'china', material: 'steel', sku: 4874, groupId: '1001' }, { country: 'japan', material: 'steel', sku: 4874, groupId: '1002' } ] */
注意事项
- 若
initialGroupId是带前缀的字符串(如'group-1'),需调整groupId递增逻辑,比如用计数器拼接前缀 - 若属性值包含
|或:,需更换分隔符(如#),避免生成的唯一键冲突 - 对于引用类型的属性值(如对象、数组),需自定义序列化逻辑生成键,否则无法正确判断属性是否相等
内容的提问来源于stack exchange,提问作者Binaromong
相关产品推荐
相关产品推荐

