kotlin - 优化 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)
}
}
解决方案
你可以做到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()
}
}