我有一个(可变的)物品清单。我想遍历此列表并检查每个项目的特定条件。满足条件后,我要在特定索引处插入(而不是替换)新项目。
在Kotlin中,最优雅的方法是什么?
附言我还没有代码示例,因为我想不出一个好方法。
编辑:用例:我想为特定项目组的列表视图添加标题。
答案 0 :(得分:4)
如果您有可变列表,则可以获取其可变的listIterator
并在迭代过程中使用该迭代器修改列表。
例如,在每个项目之后的 后面插入一个字符串,该字符串表示一个偶数:
val list = mutableListOf("1", "2", "3", "4")
val iterator = list.listIterator()
for (item in iterator) {
if (item.toInt() % 2 == 0) {
iterator.add("^ That was even")
}
}
list.forEach { println(it) }
或在当前字符串之前 之前插入字符串:
val iterator = list.listIterator()
for (item in iterator) {
if (item.toInt() % 2 == 0) {
iterator.previous()
iterator.add("Next will be even:")
iterator.next()
}
}
list.forEach { println(it) }
答案 1 :(得分:1)
正如您说的那样,您遍历列表,也许flatMap
对您来说是一件好事(在本例中,我在奇/偶元素之后添加了“奇”,“偶”):
val list = listOf("1", "2", "3", "4")
val newList = list.flatMap {
// well... actually your conditions...
when (it.toInt() % 2) {
0 -> listOf(it, "<-- that was even" /*, whatever you want to add after it */)
else -> listOf(it, "<-- that was odd" /*, whatever you want to add after it */)
}
}
现在这将为您返回一个新列表,其中包含您构造的元素,例如
[1, <-- that was odd, 2, <-- that was even, 3, <-- that was odd, 4, <-- that was even]
这样,您不一定需要可变列表。而且您相当快地掌握了列表中的内容(顺序/其他)。
如果您真的想保留可变列表并使用它,则需要确保在操作列表时不要更改列表,否则会得到ConcurrentModificationException
。
另一方面,这意味着您需要在要插入事物的位置保留索引。插入索引后,保留索引将无效,但是如果保留索引中的任何一个高于先前添加的保留索引,则该索引将无效。除非您也移动了光标(即,将先前添加的元素的数量添加到索引中)。然后,这很容易将它们向后插入。下面是一个示例,其中列表必须与地图的键匹配,并将插入其值:
val list = mutableListOf("1", "2", "3", "4", "5", "6")
val itemsToInsertAfterMatch = mapOf("1" to "odd 1", "2" to "even", "3" to "odd", "4" to "ev4n")
list.mapIndexedNotNull { index, s -> itemsToInsertAfterMatch[s]?.let { index to it } }
.reversed() // actually this ensures that we are operatoring on a separate list while we will add elements later
.forEach { list.add(it.first, it.second) }
还是,我不推荐。如果您不必(以及谁强迫您?),我不会使用这样的构造。而是隐藏了正在发生的事情(例如,什么与什么匹配?什么时候插入了什么?)。
以上所有解决方案均未解决找不到元素的情况(例如indexOf
返回-1
或itemsToInsertAfterMatch[s] == null
)。尽管添加这种情况应该足够容易。
请注意,如果您要插入的内容是静态的,则带有索引的@mTaks解决方案当然要容易些,然后要使用上面介绍的映射。根据您的病情复杂程度,他们自己的指数将无法满足您的需求。而且我只能建议您改用flatMap
。回来时更容易阅读。 indices
/ mapIndexed
解决方案宁愿隐藏正在发生的事情。您可能需要解密,每次回到它。您甚至都不考虑索引,那么为什么要打扰呢?但这也许只是我的意见;-)
答案 2 :(得分:0)
这是我的方法:
val list = mutableListOf("ab", "CD", "ef", "gH")
list.indices
.filter { list[it].toLowerCase() == list[it] }
.mapIndexed { index, it -> it + index }
.forEach { list.add(it, "XX") }
list.forEach { println(it) }
将打印:XX ab CD XX ef gH
条件是,如果list元素全部为小写,则在其前面插入元素“ XX”。
如果您只关注优雅,或者您出于学术或研究原因想探索Kotlin的功能,那很好,但是我不确定总是花哨的方式是最有效的方式。
为什么不使用传统的while
循环:
var index = 0
while (index < list.size) {
if (list[index].toLowerCase() == list[index]) {
list.add(index, "XX")
index++
}
index++
}
这不是花哨的,但可以肯定的是,它比花哨的方法更有效,甚至更有效。
答案 3 :(得分:0)
我用groupBy
val map = mutableList.map {
val groupItems = it.groupBy { (it as ListItem).section}
val mappedItems = mutableListOf<ListBaseItem>()
groupItems.forEach { section, items ->
mappedItems.add(ListHeaderItem(section, section))
mappedItems.addAll(items)
}
mappedItems
}