JavaScript数组分组转换求助:将含type字段数组转为指定结构
分组转换数组结构问题
输入数据
const input = [{ "type": "group1@action1", "label": "labelA", "placeholders": ["b", "a", "r"] }, { "type": "group1@action2", "label": "labelB", "placeholders": ["x", "y", "z"] }, { "type": "group2@action123", "label": "labelC", "placeholders": ["a", "b", "c"] }];
期望输出
[ { "group": "group1", "items": [ { "action": "action1", "label": "labelA", "placeholders": ["b", "a", "r"] }, { "action": "action2", "label": "labelB", "placeholders": ["x", "y", "z"] } ] }, { "group": "group2", "items": [ { "action": "action123", "label": "labelC", "placeholders": ["a", "b", "c"] } ] } ]
尝试的代码及问题
字符串分割代码
var key = "group1@action1"; console.log(key.substring(0,key.indexOf('@'))); console.log(key.substring(key.indexOf('@')-1, key.length));
这里截取action的逻辑错误,indexOf('@')-1会取到@前的字符,导致结果错误。
Map实现的分组代码
output = new Map; input.forEach(element => { group = element.type.substring(0,element.type.indexOf('@')); action = element.type.substring(element.type.indexOf('@')-1, element.type.length) if (!output.has(group)) { output.set(group, [element]); } else { output.get(group).push(element); } }); console.log(output);
实际得到的Map结果
Map(2) { 'group1' => [ { type: 'group1@action1', label: 'labelA', placeholders: [Array] }, { type: 'group1@action2', label: 'labelB', placeholders: [Array] } ], 'group2' => [ { type: 'group2@action123', label: 'labelC', placeholders: [Array] } ] }
使用Object.fromEntries(output)后的结果
{ group1: [{ label: "labelA", placeholders: ["b", "a", "r"], type: "group1@action1" }, { label: "labelB", placeholders: ["x", "y", "z"], type: "group1@action2" }], group2: [{ label: "labelC", placeholders: ["a", "b", "c"], type: "group2@action123" }] }
解决方案
修正后的代码
const input = [{ "type": "group1@action1", "label": "labelA", "placeholders": ["b", "a", "r"] }, { "type": "group1@action2", "label": "labelB", "placeholders": ["x", "y", "z"] }, { "type": "group2@action123", "label": "labelC", "placeholders": ["a", "b", "c"] }]; const result = Object.values(input.reduce((acc, item) => { // 分割group和action,比substring更简洁可靠 const [group, action] = item.type.split('@'); // 初始化分组结构 if (!acc[group]) { acc[group] = { group, items: [] }; } // 构造符合要求的item对象,添加到分组的items数组中 acc[group].items.push({ action, label: item.label, placeholders: item.placeholders }); return acc; }, {})); console.log(result);
代码说明
- 字符串分割:用
split('@')直接拆分type字段,避免手动计算索引的错误,直接得到group和action。 - 分组构建:通过
reduce遍历数组,以group为键存储分组结构,每个分组包含group名称和items数组。 - 结构转换:遍历每个item时,生成新的对象(移除原
type字段,添加action字段),并推入对应分组的items数组。 - 结果转换:最后用
Object.values将分组对象转换为期望的数组格式。
内容的提问来源于stack exchange,提问作者Stéphane GRILLON
相关产品推荐
相关产品推荐

