首页 > 解决方案 > 优化 for 循环以将项目添加到地图

问题描述

Kotlin 1.5.42

我有以下数据类,我需要过滤掉 2 级和 3 级值。然后我使用 for..loop 循环遍历 level2 并检查 level3 是否具有与 添加到列表parentId中的 level2 匹配的a。value当那个 level3 循环完成时,我添加到 map,键是 level2 对象,值是 level3 的列表。

IE Map<TopsProductFilterItem, List<TopsProductFilterItem>>

我一直在寻找一个更好的解决方案,它使用 kotlin 更简洁,并查看 associateBy 或 assoicateWith 是否有帮助。

data class TopsProductFilterItem(
    val value: String = "",
    val catalogSearchCustomAttribute: CatalogSearchCustomAttribute = CatalogSearchCustomAttribute(),
)

以及以下具有级别的数据类

data class CatalogSearchCustomAttribute(
        val level: Int = 0,
        val parentId: Int = 0) 

由于可以为他的班级分配许多级别,我只对级别 2 和级别 3 感兴趣。所以我将它们过滤掉如下。

private fun createMapOfLevelCategories(listOfTopsProductFilterItem: List<TopsProductFilterItem>) {
    val listOfLevel2 = listOfTopsProductFilterItem.filter { topsProductFilterItem ->
        topsProductFilterItem.catalogSearchCustomAttribute.level == 2
    }

    val listOfLevel3 = listOfTopsProductFilterItem.filter { topsProductFilterItem ->
        topsProductFilterItem.catalogSearchCustomAttribute.level == 3
    }

    val mapOfCategoryLevel2 = mutableMapOf<TopsProductFilterItem, List<TopsProductFilterItem>>()

    listOfLevel2.forEach { categoryLevel2 ->
        /* Find the parent id in the level 3 and from the level 2 value */
        val listOfCategoryLevel3 = mutableListOf<TopsProductFilterItem>()
        listOfLevel3.forEach { categoryLevel3 ->
            if(categoryLevel2.value.toInt() == categoryLevel3.catalogSearchCustomAttribute.parentId) {
                /* found a matching parent ID and value */
                listOfCategoryLevel3.add(categoryLevel3)
            }
        }
        mapOfCategoryLevel2.put(categoryLevel2, listOfCategoryLevel3)
    }
}

标签: kotlinfor-loopoptimization

解决方案


你可以做到listOfLevel2.associateWith { ... }associatedWith创建映射,其键与您调用它的可迭代对象相同,但允许您指定如何转换每个键的关联值。在这种情况下,我们希望 value 是 3 级列表中所有具有parentId等于 key 的项目value.toInt()

listOfLevel2.associateWith { level2 ->
    listOfLevel3.filter { level3 ->
        level2.value.toInt() == level3.catalogSearchCustomAttribute.parentId
    }
}

更好的是,您可以groupBy先在 3 级父 Id 上执行 a ,然后您不必listOfLevel3一遍又一遍地循环associatedWith

listOfLevel3.groupBy { it.catalogSearchCustomAttribute.parentId }.let { parentIdGroups ->
    listOfLevel2.associateWith { level2 ->
        parentIdGroups[level2.value.toInt()] ?: emptyList()
    }
}

推荐阅读