Kotlin中如何简洁遍历所有布尔值测试多参布尔函数?
问题描述
我有一个如下的Kotlin函数:
fun foo(a: Boolean, b: Boolean, c: Boolean) { /*...*/ }
我想要用所有可能的参数值来测试它,最初尝试使用范围遍历:
for (a in false..true) for (b in false..true) for (c in false..true) { val expected = ... assertThat(foo(a, b, c)).isEqualTo(expected) }
但遗憾的是Kotlin并没有BooleanRange类型。
我改用以下方式实现:
for (a in 0..1) for (b in 0..1) for (c in 0..1) { val expected = ... assertThat(foo(a == 1, b == 1, c == 1)).isEqualTo(expected) }
但这种方式不够直观。
我还试过:
for (a in arrayOf(false, true)) for (b in arrayOf(false, true)) for (c in arrayOf(false, true)) { val expected = ... assertThat(foo(a, b, c)).isEqualTo(expected) }
但这仍然太过冗长。请问有没有更简洁的方法?比如Kotlin是否有直接遍历false和true这两个值的函数?我注意到有BooleanIterator类型,但不确定是否能用在这里。
简洁实现方案
1. 复用布尔值列表常量
先定义一个包含所有布尔值的常量列表,后续循环直接复用,避免重复代码:
val booleans = listOf(false, true) for (a in booleans) for (b in booleans) for (c in booleans) { val expected = ... assertThat(foo(a, b, c)).isEqualTo(expected) }
2. 内联使用轻量序列
用sequenceOf替代arrayOf,语法更简洁且是惰性求值,性能更优:
for (a in sequenceOf(false, true)) for (b in sequenceOf(false, true)) for (c in sequenceOf(false, true)) { val expected = ... assertThat(foo(a, b, c)).isEqualTo(expected) }
3. 扩展布尔类型实现范围遍历
自己实现rangeTo扩展函数,让你最初设想的false..true语法直接生效:
operator fun Boolean.rangeTo(other: Boolean): Iterable<Boolean> { return if (this == other) listOf(this) else listOf(false, true) }
之后就能像最开始尝试的那样使用范围遍历:
for (a in false..true) for (b in false..true) for (c in false..true) { val expected = ... assertThat(foo(a, b, c)).isEqualTo(expected) }
4. 笛卡尔积处理多参数场景
如果参数数量超过3个,嵌套循环会变得非常繁琐,这时可以用笛卡尔积函数扁平化处理所有参数组合:
fun <T> cartesianProduct(vararg lists: List<T>): List<List<T>> { return lists.fold(listOf(listOf())) { acc, list -> acc.flatMap { accList -> list.map { accList + it } } } }
调用时传入布尔值列表,直接遍历生成的所有组合:
val booleans = listOf(false, true) cartesianProduct(booleans, booleans, booleans).forEach { (a, b, c) -> val expected = ... assertThat(foo(a, b, c)).isEqualTo(expected) }
内容的提问来源于stack exchange,提问作者k314159
相关产品推荐
相关产品推荐

