我有一个要处理的字符串列表,所以可以说
val List<String?> = listOf("Q", NULL, "W", "E", NULL, "E", "E", "R", "R", "T") [sic]
我想对此进行处理,以便可以在相邻位置有两个匹配字符串的情况下应用谓词,并返回不可为空的字符串的列表。
扩展名的方法签名将为
fun <T : Any> List<T?>.processList(action: (T) -> T): List<T>
让我这次的谓词是在重复的第一个字符串中添加“陷阱”,然后删除第二个,因此在这种情况下,我将以
结尾ListOf("Q", "W", "Egotcha", "E", "Rgotcha", "T")
我可以很容易地以老式的方式进行while循环
遵循这些原则的混乱版本
val nL : ArrayList<T> = ArrayList<T>()
var indexThis : Int = 0
while ( indexThis < intermediate.size-1 ) {
if (intermediate[indexThis] != intermediate[indexThis + 1]) {
nL.add(intermediate[indexThis]!!)
indexThis += 1 }
else {
nL.add(processList(intermediate[indexThis]!!))
indexThis += 2 }
}
这距离完成文章还有很长的路要走,但是这是我试图使过程清晰明了的尝试...
但是我正在努力以更实用的方式开始做它
所以我可以发现我可能想从
开始 this.filter {a -> a != null}
但是然后我看不到下一步要去哪里?那么我能想到的唯一方法是forEachIndexed,但是我对此的尝试似乎非常复杂。我确定我已经看到人们比较地图中List中的项目的例子了吗?
我的最后思路是
.map{b -> b?.run{b ... processList (b)}}
但这似乎很不正确
谁能指出我正确的方向?
答案 0 :(得分:1)
这是第一步,这在功能上有些困难,因为在累积结果时必须保持某些状态。
fun <T> List<T?>.processList(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: MutableList<T> = mutableListOf(), var previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
// skip this one that was already consumed in the dupe
accum.previousWasDupe = false
} else if (value.size < 2 || value[0] != value[1]) {
accum.resultList.add(value[0])
accum.previousWasDupe = false // already is false, you could delete this line, here for clarity
} else {
accum.resultList.add(action(value[0]))
accum.previousWasDupe = true
}
accum
}.resultList
}
针对您的测试用例:
val items = listOf("Q", null, "W", "E", null, "E", "E", "R", "R", "T")
println(items.processList { it + "gotcha" })
// prints "[Q, W, Egotcha, E, Rgotcha, T]"
您也可以使用一个不可变的累加器(我不喜欢它是可变的,但是它会更好地运行),但是鉴于状态是内部的,因此毫无意义地采取这种攻击功能。无论是作为序列(书面形式)还是与副本一起使用,效果都更好,取决于列表的大小,如果不进行性能测试,很难说。
请注意,我还确保<T>
项是Comparable
,以便我们可以确定==
达到了预期的效果,否则您真的不知道自己收到了该功能甚至可以处理的事情。
有趣的是,不可变版本:
fun <T> List<T?>.processListImmutable(action: (T) -> T): List<T> where T: Comparable<T> {
data class Accumulator(val resultList: List<T> = emptyList(), val previousWasDupe: Boolean = false)
return this.asSequence()
.filterNotNull()
.windowed(2, partialWindows = true).fold(Accumulator()) { accum, value ->
if (accum.previousWasDupe) {
Accumulator(accum.resultList, false) // could also be: accum.copy(previousWasDupe = false)
} else if (value.size < 2 || value[0] != value[1]) {
Accumulator(accum.resultList + value[0], false)
} else {
Accumulator(accum.resultList + action(value[0]), true)
}
}.resultList
}
输入要解决的一个极端情况:
val items = listOf("Q", null, "W", "E", null,
"E", "E", "R", "R", "T",
"Z", "Z", "Zgotcha") // <--- this is the trap
应返回:
[Q, W, Egotcha, E, Rgotcha, T, Zgotcha, Zgotcha]
而不是:
[Q, W, Egotcha, E, Rgotcha, T, Zgotchagotcha]
答案 1 :(得分:0)
尝试下一个代码:
IStringLocalizer