嘿,我有一个嵌套列表,我想找到第一次出现的索引值。
data class ABC(
val key: Int,
val value: MutableList<XYZ?>
)
data class XYZ)
val isRead: Boolean? = null,
val id: String? = null
)
我添加了找到XYZ对象的代码,但我需要找到索引。那么我怎样才能以有效的方式实现。我如何改进我的代码?
list?.flatMap { list ->
list.value
}?.firstOrNull { it?.isRead == false }
如果你想坚持函数式风格,那么你可以这样做:
val result = list.asSequence()
.flatMapIndexed { outer, abc ->
abc.value.asSequence()
.mapIndexed { inner, xyz -> Triple(outer, inner, xyz) }
}
.find { it.third?.isRead == false }
if (result != null) {
val (outer, inner) = result
println("Outer: $outer, inner: $inner")
}
对于每个ABC
项,我们将其索引记为outer
,并将其XYZ
项列表映射/转换为元组列表:(outer, inner, xyz)
。然后flatMap
将所有这样的列表(每个ABC
项有一个列表)合并为(outer, inner, xyz)
的单个扁平列表。
换句话说,整个flatMapIndexed()
块改变了这个(伪代码):
[ABC([xyz1, xyz2]), ABC([xyz3, xyz4, xyz5])]
这:
[
(0, 0, xyz1),
(0, 1, xyz2),
(1, 0, xyz3),
(1, 1, xyz4),
(1, 2, xyz5),
]
然后我们用find()
搜索特定的xyz
条目,我们得到了附在它上面的outer
和inner
。
asSequence()
在这两个地方改变了它内部的工作方式。序列是懒惰的,这意味着它们只在需要时执行计算,并且在进入另一个项目之前尝试处理单个项目。如果没有asSequence()
,我们将首先创建一个包含所有xyz
项的完整列表,如上面的示例所示。然后,如果xyz2
是我们搜索的,那就意味着我们浪费了时间来处理xyz3
,xyz4
和xyz5
,因为我们对它们不感兴趣。
对于asSequence()
,我们从来没有真正创建这个平面列表,而是对每个项目执行所有操作。find()
要求检查下一个项目,mapIndexed
只映射一个项目,flatMapIndexed
也只映射这个项目,如果find()
成功,其余项目不处理。
list.indicesOfFirstXyzOrNull { it?.isRead == false }
inline fun Iterable<ABC>.indicesOfFirstXyzOrNull(predicate: (XYZ?) -> Boolean): Pair<Int, Int>? {
forEachIndexed { outer, abc ->
abc.value.forEachIndexed { inner, xyz ->
if (predicate(xyz)) {
return outer to inner
}
}
}
return null
}
在Kotlin中,您可以使用indexOf()
函数返回给定元素第一次出现的索引,如果数组不包含该元素,则使用-1
函数。
的例子:
fun findIndex(arr: Array<Int>, item: Int): Int {
return arr.indexOf(item)
}