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方法会返回第一个匹配的键,无法保证这是最长的公共前缀
优化后的实现方案
核心思路
- 先提取所有键,为每个键筛选出原键列表中作为其前缀的所有候选
- 从候选前缀中取长度最长的那个,作为该键的分组键
- 基于分组键完成归类,避免不必要的对象拷贝提升性能
代码实现
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
相关产品推荐
相关产品推荐

