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

JavaScript:按最长公共前缀分组对象键的最优实现问询

按最长公共前缀对对象键分组的优化实现

需求背景

给定如下JavaScript对象:

{
   apple: 3,
   apple-02: { /* stuff */ },
   apple124: 'morestuff',
   banana: 5,
   bananaPhone: 'morestuff',
   cherry: 10,
}

需要将对象的键按照最长公共前缀进行分组,最终得到如下结构:

{
    apple: {
       apple: 3,
       apple-02: { /* stuff */ },
       apple124: 'morestuff',
    },
    banana: {
       banana: 5,
       bananaPhone: 'morestuff',
    },
    cherry: { cherry: 10 }
}

现有代码的问题

你当前实现的代码存在逻辑缺陷和性能问题:

Object.keys(data).reduce((accumulator, key) => {
    const existingKey = Object.keys(accumulator).find(k => key.includes(k))
    if (existingKey) {
        return { ...accumulator, [existingKey]: { ...accumulator[existingKey], [key]: data[key] } }
    }
    return { ...accumulator, [key]: { [key]: data[key] } }
}, {})

具体问题点:

  • 逻辑错误:key.includes(k)会匹配任意包含关系,比如如果有键app和apple,会错误地把apple归类到app组,完全不符合「最长公共前缀」的要求
  • 性能低下:每次循环都要遍历累加器的所有键,且每次更新都用对象展开(...)创建新对象,数据量大时会有明显的性能损耗
  • 匹配不准确:find方法会返回第一个匹配的键,无法保证这是最长的公共前缀

优化后的实现方案

核心思路

  1. 先提取所有键,为每个键筛选出原键列表中作为其前缀的所有候选
  2. 从候选前缀中取长度最长的那个,作为该键的分组键
  3. 基于分组键完成归类,避免不必要的对象拷贝提升性能

代码实现

function groupByLongestCommonPrefix(data) {
    const keys = Object.keys(data);

    // 找到当前键对应的最长公共前缀(必须是原键列表中的成员)
    const getLongestMatchingPrefix = (key) => {
        return keys
            .filter(k => key.startsWith(k))
            .sort((a, b) => b.length - a.length)[0] || key;
    };

    return keys.reduce((acc, key) => {
        const prefix = getLongestMatchingPrefix(key);
        // 初始化分组对象(如果不存在)
        if (!acc[prefix]) {
            acc[prefix] = {};
        }
        // 直接赋值,避免对象展开的性能损耗
        acc[prefix][key] = data[key];
        return acc;
    }, {});
}

方案优势

  • 准确性:通过startsWith确保前缀匹配,再按长度倒序排序取最长项,完美贴合「最长公共前缀」的需求
  • 性能优化:去掉了不必要的对象展开操作,直接修改累加器对象;前缀筛选逻辑精准,避免无效匹配
  • 鲁棒性:即使存在嵌套前缀(如app、apple),也会正确将apple及其衍生键分到apple组,而非更短的app组

测试示例

用给定数据测试:

const testData = {
   apple: 3,
   apple-02: { /* stuff */ },
   apple124: 'morestuff',
   banana: 5,
   bananaPhone: 'morestuff',
   cherry: 10,
};

console.log(groupByLongestCommonPrefix(testData));

输出结果与期望完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 21:07:02