如何在不冻结浏览器的情况下匹配含70万+条目的两大数组经纬度项
优化大列表经纬度匹配性能方案
原代码的核心问题
原代码采用嵌套遍历逻辑(大列表forEach嵌套小列表forEach),时间复杂度达到O(n*m)——n是70万+的大列表条目,m是1000条的小列表,总操作量超7亿次,直接导致浏览器主线程阻塞冻结。另外原代码中exists变量始终未被赋值为true,去重逻辑完全失效,会重复添加相同项。
优化思路:用哈希表降低查询成本
把小列表的经纬度信息存入哈希表(推荐用Map),将经纬度组合作为唯一键,对应的值为小列表中的对象。遍历大列表时,直接用当前项的经纬度去哈希表中查询匹配项,时间复杂度降至O(n+m),总操作量仅70万+1000次,彻底解决性能问题。
优化后的代码
// 第一步:用Map存储小列表的经纬度映射 const smallLatLngMap = new Map(); smallList.forEach(item => { // 用「纬度,经度」作为唯一键,若存在精度误差可先统一保留固定小数位 const key = `${item.latitude},${item.longitude}`; // 提前过滤小列表内的重复经纬度项 if (!smallLatLngMap.has(key)) { smallLatLngMap.set(key, item); } }); // 第二步:遍历大列表匹配经纬度,收集结果 const matchingList = []; // 用Set记录已添加的address,避免重复 const addedAddresses = new Set(); bigList.forEach(item => { const key = `${item.latitude},${item.longitude}`; const matchedItem = smallLatLngMap.get(key); if (matchedItem) { if (!addedAddresses.has(matchedItem.address)) { matchingList.push(matchedItem); addedAddresses.add(matchedItem.address); // 保留原代码的日志输出 console.log(matchedItem.address); } } });
额外注意点
- 若经纬度存在精度差异(如一个是
39.9042,另一个是39.904201),可先对经纬度做四舍五入处理(比如保留4位小数),再生成匹配键,避免因精度问题漏匹配。 - 若不需要按address去重,可直接去掉
addedAddresses相关逻辑,简化代码。 - 若浏览器内存压力大,可通过
setTimeout分批次遍历大列表,拆分任务避免一次性占用过多内存。
内容的提问来源于stack exchange,提问作者Axel chaparro
相关产品推荐
相关产品推荐

