You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效按key分组非唯一ID对象数组?有无适配Lodash方法?

连续相同值分组的高效实现方案

你提到的需求是将数组中连续拥有相同a值的对象分组,而不是把所有相同a值的对象归为一组(Lodash的_.groupBy会做后者,不符合你的预期结果)。针对这个需求,不管用Lodash还是原生JS,都可以用一次遍历的方式实现O(n)的时间复杂度,完全适合处理几百个对象的场景,比你之前考虑的递归检查高效太多。

方法一:使用Lodash实现

Lodash没有直接提供“连续分组”的内置方法,但可以用_.reduce快速实现,代码简洁且高效:

const arr = [ { a: 1 }, { a: 1 }, { a: 2 }, { a: 1 }, { a: 1 }, { a: 1 } ];

const grouped = _.reduce(arr, (result, current) => {
  // 检查结果数组是否为空,或者最后一组的第一个元素与当前元素的a值不同
  if (_.isEmpty(result) || _.last(result)[0].a !== current.a) {
    result.push([current]);
  } else {
    // 若相同则将当前元素加入最后一组
    _.last(result).push(current);
  }
  return result;
}, []);

console.log(grouped);
// 输出:[ [{ a: 1 }, { a: 1 }], [{ a: 2 }], [{ a: 1 }, { a: 1 }, { a: 1 }] ]

方法二:原生JS高效实现

如果不想依赖Lodash,原生JS的Array.reduce同样可以轻松实现,而且性能上不会有额外开销:

const arr = [ { a: 1 }, { a: 1 }, { a: 2 }, { a: 1 }, { a: 1 }, { a: 1 } ];

const grouped = arr.reduce((result, current) => {
  const lastGroup = result.at(-1); // 取最后一组(ES2022+语法,也可以用result[result.length - 1])
  if (!lastGroup || lastGroup[0].a !== current.a) {
    result.push([current]);
  } else {
    lastGroup.push(current);
  }
  return result;
}, []);

console.log(grouped);
// 得到完全一致的预期结果

通用化扩展(可选)

如果你的分组键不是固定的a,可以把分组逻辑抽成通用函数,适配更多场景:

// 原生JS通用连续分组函数
function groupConsecutiveBy(arr, getKey) {
  return arr.reduce((result, item) => {
    const lastGroup = result.at(-1);
    if (!lastGroup || getKey(lastGroup[0]) !== getKey(item)) {
      result.push([item]);
    } else {
      lastGroup.push(item);
    }
    return result;
  }, []);
}

// 使用示例:按a值分组
const grouped = groupConsecutiveBy(arr, item => item.a);
// 也可以按其他键分组,比如如果对象有b键:groupConsecutiveBy(arr, item => item.b)

为什么这个方案高效?

整个过程只需要遍历数组一次,每个元素仅被处理一次,时间复杂度为O(n),相对于你之前考虑的递归检查所有历史元素(时间复杂度O(n²)),性能提升非常明显,即使数组中有几千个元素也能快速完成分组。

内容的提问来源于stack exchange,提问作者Sam Denty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:50:44