数组提取问题:过滤玩家已拥有的可攻击领地
问题背景
我创建了存储领地信息的fullTerritoriesInRange数组,结构示例如下:
[ [ [ "7", "Vatican City" ], [ [ "Italy", [ { "x": 1311.7569580078126, "y": 156.45799255371095 }, // 更多坐标数据 ], 0.8130994663446266 ], // 其他可达领地条目 ] ] ]
该数组中每个元素包含当前领地(如示例中的Vatican City)和其所有可达领地列表。我需要生成attackableTerritoriesInRange数组,过滤掉玩家已拥有的领地——玩家的领地信息存储在arrayOfLeadersAndCountries数组中,通过.territoryName属性判断。
现有代码的问题
现有实现逻辑错误,导致异常:
- 当
fullTerritoriesInRange[j][1](可达领地列表)长度大于1时,返回空数组 - 当长度为1时,重复添加全部领地
现有代码:
const attackableTerritoriesInRange = []; for (let j = 0; j < fullTerritoriesInRange.length; j++) { let isOwned = false; // 标记是否存在匹配的已拥有领地 for (let k = 0; k < fullTerritoriesInRange[j][1].length; k++) { const territoryNameToCheck = fullTerritoriesInRange[j][1][k][0]; for (let l = 0; l < arrayOfLeadersAndCountries[i][2].length; l++) { const ownedTerritoryName = arrayOfLeadersAndCountries[i][2][l].territoryName; if (territoryNameToCheck === ownedTerritoryName) { isOwned = true; break; } } if (isOwned) { break; } } if (!isOwned) { attackableTerritoriesInRange.push(fullTerritoriesInRange[j][1]); } console.log("and the attackable territories are:"); console.log(attackableTerritoriesInRange); }
核心错误:原代码逻辑是「只要当前可达领地列表中有一个领地是玩家拥有的,就丢弃整个列表」,但实际需求是「过滤掉列表中已拥有的领地,保留剩余部分」。
修复方案
思路
- 先提取玩家所有已拥有的领地名称,存入
Set(利用Set的O(1)查找效率优化性能) - 遍历
fullTerritoriesInRange的每个条目,对其可达领地列表进行过滤:- 检查每个领地名称是否不在已拥有列表中
- 保留符合条件的领地
- 将过滤后的有效领地列表(非空时)加入结果数组
修复后的代码
// 1. 提取玩家已拥有的领地名称到Set const ownedTerritoryNames = new Set(); // 假设i是当前玩家的索引(和原代码保持一致) const playerTerritories = arrayOfLeadersAndCountries[i][2]; playerTerritories.forEach(territory => { ownedTerritoryNames.add(territory.territoryName); }); const attackableTerritoriesInRange = []; // 2. 遍历fullTerritoriesInRange,过滤每个条目下的可达领地 for (let j = 0; j < fullTerritoriesInRange.length; j++) { const currentTerritoryReachables = fullTerritoriesInRange[j][1]; // 过滤掉已拥有的领地 const filteredReachables = currentTerritoryReachables.filter(territoryEntry => { const territoryName = territoryEntry[0]; return !ownedTerritoryNames.has(territoryName); }); // 如果过滤后还有领地,才加入结果 if (filteredReachables.length > 0) { attackableTerritoriesInRange.push(filteredReachables); } } console.log("and the attackable territories are:"); console.log(attackableTerritoriesInRange);
代码说明
- 使用
Set存储已拥有领地名称,比嵌套循环查找效率更高,尤其是当领地数量较多时 - 使用
filter方法直接过滤可达领地列表,逻辑更清晰,避免嵌套循环的混乱 - 添加了非空判断,避免结果数组中出现空的领地列表(如果不需要可以去掉这个判断)
内容的提问来源于stack exchange,提问作者Leigh Hobson
相关产品推荐
相关产品推荐

