首页 > 解决方案 > 在匹配值并满足条件的 3 个数组之间进行迭代的更快方法?打字稿

问题描述

所以我在尝试以超过 20 秒的速度构建 Excel 工作表时遇到了麻烦。我正在使用下面的内容来比较 3 个不同的数组,然后打印出我需要的答案。

for (let i = 0; i < this.arrayNumberOne[0].length; i++) {
    let orangeOne = this.arrayNumberOne[0][i]['item_1'];
    let orangeTwo = this.arrayNumberOne[0][i]['item_2'];
    let orangeThree = orangeOne.concat(orangeTwo)

    for (let k = 0; k < this.arrayNumberTwo[0].length; k++) {
        let appleOne = this.arrayNumberTwo[0][k]['item_1'];
        
        for (let j = 0; j < this.arrayNumberThree[0].length; j++) {
            let grapeOne = this.arrayNumberThree[0][j]['item_1'];
            let grapeTwo = this.arrayNumberThree[0][j]['item_2'];
            let grapeThree = this.arrayNumberThree[0][j]['item_3'];
        
            if (orangeThree == grapeOne && appleOne == grapeTwo) {

                if (grapeThree == null || grapeThree == '') {
                    // print to response to excel
                }

                else if (grapeThree == 'sells') {
                    //  print stuff to excel
                }

                else if (grapeThree == 'buys') {
                    // print stuff to excel
                }
            }
        }
    }
}

我正在查看哈希图和接口,但我不太确定如何在这里应用它。我将不胜感激任何使上述速度更快的替代方案。

编辑:

excel输出示例

游乐场链接

标签: arraystypescripthashmapiteration

解决方案


在这里引发危险的是您有 3 个嵌套循环,但您的数据是 2D 的,因此您最多期望 2 个嵌套循环(一个用于 X,一个用于 Y)。您要关注的是获取每个单元格值的过程应该尽可能快,因为这是需要发生的次数最多的事情。

这里的关键是预处理您的值(电子表格单元格中的内容,购买/出售/空白),使其快速查找这些值。

例如:

// Index all actions by player id and item name
const indexedActions: {
    [playerId: string]: {
        [itemCatName: string]: string
    }
} = {}

// Loop through all actions once to index them.
for (const {playerId, itemCatName, action} of actions) {
    if (!indexedActions[playerId]) indexedActions[playerId] = {}
    indexedActions[playerId][itemCatName] = action
}

运行后,您将获得如下数据:

{
    "12": {
        "potionsmall-potion": 'buy'
        // etc...
    }
    // etc...
}

这很重要,因为现在查找任何单元格都非常简单:

indexedActions[playerId][itemName]

这使您可以完全删除最内部的循环。

// Loop through items
for (let i = 0; i < items.length; i++) {
    let itemCat = items[i]['itemCategory']
    let itemNam = items[i]['itemName']
    let combineCat = itemCat.concat(itemNam)
    
    // Loop through players
    for (let k = 0; k < players.length; k++) {
        let playerIdentify = players[k]['playerId']
        
        // Lookup what this player did with this item
        const actionToDo = indexedActions[playerIdentify][combineCat]

        // do stuff with action
    }
}

优化前

  • 对于每个项目
    • 为每一位玩家
      • 对于每一个动作
        • 逻辑()

这里的“doLogic”是执行itemCount * playerCount * actionCount次数。

优化后

  • 对于每一个动作
    • 索引每个动作
  • 对于每个项目
    • 为每一位玩家
      • 逻辑()

现在我们在前面做了更多的工作,但doLogic只是执行itemCount * playerCount时间,这是一个巨大的改进。

作为奖励,它的代码更少,更易于阅读!

看游乐场


推荐阅读