如何用循环或哈希表优化数组可重复元素的起止位置计算函数?
优化数组分组位置计算函数的实现
你现在的代码能跑,但有两个明显的问题:
- 性能拉胯:
data.map(el => data.indexOf(el))会让时间复杂度变成O(n²)——每次indexOf都要把整个数组扫一遍找元素的第一个位置,数组大了之后卡得很明显。 - 逻辑有漏洞:靠
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
相关产品推荐
相关产品推荐

