如何将字符串数组按相同子串分组转换为对象数组?
字符串数组按前缀子串分组转对象数组的最优实现方法
问题分析
你尝试用map方法实现分组,但map是一对一转换,只能给每个元素生成独立对象,没办法把多个同前缀的元素合并到同一个对象的数组属性里,所以得用更适合累积操作的方法。
最优实现方案
基础版(适合小规模数据)
用reduce方法遍历数组,同时累积分组结果:
const parameters = ["product_groups", "product_filters", "location_groups"]; const desiredOutput = parameters.reduce((acc, curr) => { // 提取下划线前的前缀作为分组键 const groupKey = curr.split('_')[0]; // 查找当前分组是否已存在 const existingGroup = acc.find(item => Object.keys(item)[0] === groupKey); if (existingGroup) { // 已有分组,追加当前元素到数组 existingGroup[groupKey].push(curr); } else { // 无对应分组,新增对象加入结果数组 acc.push({ [groupKey]: [curr] }); } return acc; }, []);
优化版(适合大数据量)
上面的find每次会遍历结果数组,数据量大时性能一般。可以用一个临时索引映射表,把分组键和结果数组中的索引绑定,将查找时间从O(n)降到O(1):
const parameters = ["product_groups", "product_filters", "location_groups"]; const { result: desiredOutput } = parameters.reduce(({ result, indexMap }, curr) => { const groupKey = curr.split('_')[0]; if (indexMap.hasOwnProperty(groupKey)) { // 通过索引直接找到分组,追加元素 result[indexMap[groupKey]][groupKey].push(curr); } else { // 新增分组,记录索引 const newGroup = { [groupKey]: [curr] }; result.push(newGroup); indexMap[groupKey] = result.length - 1; } return { result, indexMap }; }, { result: [], indexMap: {} });
效果验证
两种方法最终都会输出你期望的结果:
[ { product: ["product_groups", "product_filters"] }, { location: ["location_groups"] } ];
内容的提问来源于stack exchange,提问作者Dennis Zab
相关产品推荐
相关产品推荐

