如何按Fruit分组并获取每组价格最低的对象(JavaScript)
按水果分组并保留每组价格最低的对象
原始数据
const fruits = [ { id: 1, fruit: "apple", store: "store1", price: 1 }, { id: 2, fruit: "apple", store: "store2", price: 1.25 }, { id: 3, fruit: "banana", store: "store1", price: 0.5 }, { id: 4, fruit: "banana", store: "store2", price: 0.75 }, { id: 5, fruit: "Orange", store: "store3", price: 5 }, { id: 6, fruit: "Orange", store: "store1", price: 5.1 }, { id: 7, fruit: "Cherry", store: "store1", price: .1 }, { id: 8, fruit: "Cherry", store: "store1", price: .6 }, { id: 9, fruit: "", store: "store1", price: 0.5 } ]
已实现的分组排序代码
我已经实现了按fruit分组并按价格升序排列的逻辑:
const groupBy = (fruits.sort((a, b) => a.price - b.price)).reduce((grouped, object) => { let x = object["fruit"] if (!grouped[x]) { grouped[x] = [] } grouped[x].push(object) return grouped }, [])
输出符合预期:
"": [{…}] Cherry: (2) [{…}, {…}] Orange: (2) [{…}, {…}] apple: (2) [{…}, {…}] banana: (2) [{…}, {…}]
当前需求与问题
现在需要修改逻辑,仅保留每组中价格最低的对象,但尝试了以下代码后输出和之前一致,求正确实现方式:
const groupBy = (fruits.sort((a, b) => a.price - b.price)).reduce((grouped, object) => { let x = object["fruit"] if (!grouped[x]) { grouped[x] = [] } else if (grouped[x]?.price < object?.price) { let c = grouped[x] return grouped[x] } grouped[x].push(object) return grouped }, [])
错误原因
你这段代码的问题出在这几个地方:
grouped[x]是数组而非单个对象,grouped[x]?.price无法取到有效值,条件永远不成立- 逻辑判断写反:你想保留最低价,但条件却判断“已有分组的价格小于当前对象价格”,就算成立也只是返回数组,没有做任何有效更新
- 无论条件是否成立,最后都会执行
push操作,导致结果和之前完全一致
正确实现方法
方法一:利用已排序的特性(推荐)
既然已经把数组按价格升序排好,每组的第一个元素就是价格最低的。reduce时只要当前分组不存在,就存入当前对象,已存在则直接跳过:
// 复制原数组再排序,避免修改原数据 const sortedFruits = [...fruits].sort((a, b) => a.price - b.price); const groupByMinPrice = sortedFruits.reduce((grouped, obj) => { const key = obj.fruit; // 分组不存在时存入当前对象(排序后第一个就是最低价) if (!grouped[key]) { grouped[key] = obj; } return grouped; }, {});
输出结果:
"": {id: 9, fruit: "", store: "store1", price: 0.5} Cherry: {id: 7, fruit: "Cherry", store: "store1", price: 0.1} Orange: {id: 5, fruit: "Orange", store: "store3", price: 5} apple: {id: 1, fruit: "apple", store: "store1", price: 1} banana: {id: 3, fruit: "banana", store: "store1", price: 0.5}
方法二:不排序,直接在reduce中比较价格
如果不想提前排序,可在遍历过程中直接比较当前对象与分组中已存对象的价格,保留更低的那个:
const groupByMinPrice = fruits.reduce((grouped, obj) => { const key = obj.fruit; if (!grouped[key]) { grouped[key] = obj; } else { // 当前对象价格更低时替换已存对象 if (obj.price < grouped[key].price) { grouped[key] = obj; } } return grouped; }, {});
这个方法无需提前排序,遍历一次即可完成,效率更高。
内容的提问来源于stack exchange,提问作者Sharanjeet Singh
相关产品推荐
相关产品推荐

