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

如何用循环或哈希表优化数组可重复元素的起止位置计算函数?

优化数组分组位置计算函数的实现

你现在的代码能跑,但有两个明显的问题:

  1. 性能拉胯:data.map(el => data.indexOf(el)) 会让时间复杂度变成O(n²)——每次indexOf都要把整个数组扫一遍找元素的第一个位置,数组大了之后卡得很明显。
  2. 逻辑有漏洞:靠Set的插入顺序来保证分组顺序虽然在ES6+里能work,但如果数组里出现非连续的重复元素(比如["Test1", "Test2", "Test1"]),原代码会错误地把两个Test1合并成一个分组,不符合你“连续重复才算独立分组”的要求。

下面给你两个优化方案,都是O(n)时间复杂度,性能和鲁棒性都强很多:

方案1:一次遍历直接分组(最推荐)

只扫一遍数组,跟踪当前分组的名称和起始索引,碰到不一样的元素就把当前分组的信息算好塞进结果,最后处理最后一个分组的结束位置:

const data = [
  "Test1", "Test1",
  "Test2", "Test2", "Test2",
  "Test3", "Test3", "Test3", "Test3",
  "Test4", "Test4", "Test4"
];

function calcComponent(data: string[]) {
  if (data.length === 0) return [];

  const result: { name: string; start: string; end: string }[] = [];
  let currentName = data[0];
  let startIndex = 0;

  // 从第二个元素开始遍历
  for (let i = 1; i < data.length; i++) {
    if (data[i] !== currentName) {
      // 计算百分比
      const start = `${startIndex * 10}%`;
      const end = `${i * 10}%`;
      result.push({ name: currentName, start, end });

      // 更新当前分组的信息
      currentName = data[i];
      startIndex = i;
    }
  }

  // 处理最后一个分组,结束固定为120%
  const lastStart = `${startIndex * 10}%`;
  result.push({ name: currentName, start: lastStart, end: "120%" });

  console.log(result);
  return result;
}

calcComponent(data);

这个方案的好处:

  • 速度快,只扫一遍数组,大数据量下优势明显。
  • 逻辑直白,完全贴合你“连续重复元素算独立分组”的要求,就算数组里有非连续重复元素也能正确处理。
  • 不用额外搞Set、Map这些,内存占用也少。

方案2:用哈希表存分组边界(适合需要复用分组数据的场景)

如果之后还要用到每个分组的原始索引边界,可以用Map先存起来,再转成需要的格式:

const data = [
  "Test1", "Test1",
  "Test2", "Test2", "Test2",
  "Test3", "Test3", "Test3", "Test3",
  "Test4", "Test4", "Test4"
];

function calcComponent(data: string[]) {
  if (data.length === 0) return [];

  const groupMap = new Map<string, { start: number; end: number }>();
  let currentName = data[0];
  let startIndex = 0;

  for (let i = 1; i < data.length; i++) {
    if (data[i] !== currentName) {
      groupMap.set(currentName, { start: startIndex, end: i });
      currentName = data[i];
      startIndex = i;
    }
  }
  // 把最后一个分组也存进去
  groupMap.set(currentName, { start: startIndex, end: data.length });

  // 转成要求的结果格式
  const result = Array.from(groupMap.entries()).map(([name, pos], index, arr) => {
    const start = `${pos.start * 10}%`;
    const end = index === arr.length - 1 ? "120%" : `${pos.end * 10}%`;
    return { name, start, end };
  });

  console.log(result);
  return result;
}

calcComponent(data);

这个方案的好处是额外存了分组的原始索引,后面如果有其他逻辑要用到这些数据就很方便,性能同样是O(n)。

两个方案的输出和你原代码完全一致,但性能和可靠性都提升了不少。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 03:24:24