如何使用Ruby格式化对象数组?含分组转换需求示例
如何将汽车对象数组按品牌分组格式化?
初始数组:
const cars = [ {model: 'nissan', type: 'wingroad'}, {model: 'nissan', type: 'sunny'}, {model: 'nissan', type: 'terrano'}, {model: 'toyota', type: 'hilux'} ];期望输出:
const formatted_cars = [ {name: 'nissan', value: ['wingroad', 'sunny', 'terrano']}, {name: 'toyota', value: ['hilux']} ];请问是否需要通过map遍历结合inject方法,再运用合并技巧来生成这个格式化后的数组?还是有其他更合适的实现方式?
嘿,这个分组格式化的需求其实挺常见的,你提到的inject(JS里叫reduce)确实是非常合适的工具,而且完全不需要额外搭配map就能搞定,写法还很简洁。当然也有其他灵活的实现方式,我给你拆解下:
方法一:用reduce(对应Ruby的inject)一步到位
这应该是最高效直接的方式,一次遍历就能完成分组和格式转换:
const cars = [ {model: 'nissan', type: 'wingroad'}, {model: 'nissan', type: 'sunny'}, {model: 'nissan', type: 'terrano'}, {model: 'toyota', type: 'hilux'} ]; const formatted_cars = Object.values(cars.reduce((acc, car) => { // 如果当前品牌还没在累加器里,就初始化目标结构 if (!acc[car.model]) { acc[car.model] = { name: car.model, value: [] }; } // 把车型推入对应品牌的数组 acc[car.model].value.push(car.type); return acc; }, {})); console.log(formatted_cars);
简单说下逻辑:
- 先用
reduce把原数组转换成一个以品牌名为key的对象,每个key对应你想要的{name, value}结构 - 最后用
Object.values()把对象里的所有值提取出来,就是目标数组了
如果是在Ruby环境下,写法逻辑完全一致,用inject构建哈希再转数组:
cars = [ {model: 'nissan', type: 'wingroad'}, {model: 'nissan', type: 'sunny'}, {model: 'nissan', type: 'terrano'}, {model: 'toyota', type: 'hilux'} ] formatted_cars = cars.inject({}) do |acc, car| acc[car[:model]] ||= { name: car[:model], value: [] } acc[car[:model]][:value] << car[:type] acc end.values p formatted_cars
方法二:用ES6 Map对象分组(JS环境)
如果你觉得对象key只能是字符串有点局限(虽然这里品牌都是字符串),用Map会更灵活,逻辑也很清晰:
const carMap = new Map(); // 先完成车型分组 cars.forEach(car => { if (!carMap.has(car.model)) { carMap.set(car.model, []); } carMap.get(car.model).push(car.type); }); // 把Map转换成目标数组格式 const formatted_cars = Array.from(carMap, ([name, value]) => ({ name, value }));
总结
你说的map+inject其实有点绕,直接用inject/reduce就足够覆盖需求了,不需要额外的map遍历。上面两种方法都是O(n)的时间复杂度,效率拉满,选哪种完全看你个人习惯就行~
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

