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

如何优化excludeItems函数?现有两种实现求更优解

关于excludeItems函数的优化实现提问

需求说明

编写一个名为excludeItems的函数:

  • 第一个入参是数据集(对象数组)
  • 第二个入参是需排除的键值属性(对象数组)
  • 返回排除指定键值属性后的数组

示例代码

const items = [
  { color: 'red', type: 'tv', age: 18 },
  { color: 'red', type: 'phone', age: 20 },
  { color: 'silver', type: 'tv', age: 18 },
  { color: 'silver', type: 'phone', age: 20 }
];

const excludes = [
  { k: 'color', v: 'red' },
  { k: 'color', v: 'blue' },
  { k: 'type', v: 'phone' },
];

expectedOutput = [
  { type: 'tv', age: 18 },
  { age: 20 },
  { color: 'silver', type: 'tv', age: 18 },
  { color: 'silver',  age: 20 }
];

现有实现

我已经写出两种相似的解决方案,个人觉得第二种略优——不需要遍历值列表检查原对象的值是否存在。想请教有没有更高效的实现方式?

方案1

// Option 1
function excludeItems(items, excludes) {
  let exclusionMap = {};
  let results = [];

  excludes.forEach(item => {
    if(!exclusionMap[item.k])
        exclusionMap[item.k] = [];
     
    let itemDoesNotExist = exclusionMap[item.k].indexOf(item.v) === -1;
    if(itemDoesNotExist) {
        exclusionMap[item.k].push(item.v);
    }
  })
  
  results = items.map(item => {
    for(let key in exclusionMap) {
      let exclusionValues = exclusionMap[key];
      if(item[key]) {
        let itemValue = item[key]
        let itemValueIndexInExclusionValue = exclusionValues.indexOf(itemValue);
        
        if(itemValueIndexInExclusionValue !== -1) {
            delete item[key];
        }
      }
    }
    
    return item;
  });
  
  return results;
}

方案2

// Option 2
function excludeItems(items, excludes) {
    let exclusionMap = {};
  let results = [...items];
  
  excludes.forEach(item => {
    exclusionMap[item.k + '_' + item.v] = true;
  })
  
  
  results.map(item => {
    for(const key in exclusionMap) {
      const k = key.split('_')[0]; // type
      const v = key.split('_')[1]; // phone
      if(v == item[k]) {
        delete item[k]
      }
    }
    return item;
  })
  return results;
}

更优实现建议

现有方案存在两个明显痛点:方案1用数组存排除值,indexOf是O(n)查找效率低;方案2用k_v拼接键,若键/值本身包含_会导致拆分错误。推荐以下两种优化方案:

优化方案一:嵌套Set映射(高效无冲突)

function excludeItems(items, excludes) {
  // 构建嵌套排除规则:{ 键名: Set(需排除的值集合) }
  const exclusionMap = {};
  excludes.forEach(({ k, v }) => {
    if (!exclusionMap[k]) {
      exclusionMap[k] = new Set();
    }
    exclusionMap[k].add(v);
  });

  // 生成新对象,避免修改原数据
  return items.map(item => {
    const newItem = { ...item };
    for (const key in exclusionMap) {
      if (newItem.hasOwnProperty(key) && exclusionMap[key].has(newItem[key])) {
        delete newItem[key];
      }
    }
    return newItem;
  });
}

优化点说明

  • O(1)查找效率:Set.has()是常数时间操作,远快于数组indexOf的线性查找
  • 避免原数据污染:用{ ...item }创建新对象,不会改动原数组的对象引用
  • 无键冲突风险:嵌套结构不会因为键/值包含特殊字符出错
  • 自动去重规则:Set会自动过滤excludes中的重复规则,无需手动判断

优化方案二:预存需检查的键(极致性能)

如果数据集和排除规则很大,可以进一步减少循环次数:

function excludeItems(items, excludes) {
  const exclusionMap = {};
  const exclusionKeys = new Set(); // 预存所有需要检查的键

  excludes.forEach(({ k, v }) => {
    if (!exclusionMap[k]) {
      exclusionMap[k] = new Set();
      exclusionKeys.add(k);
    }
    exclusionMap[k].add(v);
  });

  return items.map(item => {
    const newItem = { ...item };
    // 只遍历需要检查的键,跳过无关键
    exclusionKeys.forEach(key => {
      if (newItem[key] && exclusionMap[key].has(newItem[key])) {
        delete newItem[key];
      }
    });
    return newItem;
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 21:50:39