使用谓词映射集合

Mapping over a collection with a predicate

我想 map 使用谓词这样的集合:

  1. 如果谓词为假,映射应该停止
  2. 生成的集合必须包含谓词为假的元素
  3. 谓词为假后不应发生其他映射。

Sequence.takeWhile满足1和3但不满足2

takeWhile的例子:

val seq = listOf(1, 2, 3, 4).asSequence()
seq.map { println("mapping: $it"); it }
    .takeWhile { it < 3 }
    .also { println(it.toList()) }    }

输出为

mapping: 1
mapping: 2
mapping: 3
[1, 2]

我需要的结果是 [1, 2, 3]

我不认为标准库中有这样的东西。如果你想坚持使用标准库函数,你很可能需要迭代序列两次。

这是您自己可以轻松实现的东西:

fun <T> Sequence<T>.inclusivelyTakeWhile(predicate: (T) -> Boolean) = sequence {
    for (t in this@inclusivelyTakeWhile) {
        yield(t)
        if (!predicate(t)) {
            break
        }
    }
}

然后做:

seq.map { println("mapping: $it"); it }
    . inclusivelyTakeWhile { it < 3 }
    .also { println(it.toList()) }  

产生了想要的结果。

standard library's implementation of TakeWhileSequence 相比,此处使用sequence 函数可能会增加一些开销。如果您关心这一点,您可以创建 TakeWhileSequence 和 return 的修改版本。