Kotlin zipAll替代

Kotlin的功能是否像Scala中的zipAll一样?

在scala我可以做两个不同长度的数组的总和使用zipAll函数。

斯卡拉:

val arrA = Array(1,2,3) val arrB = Array(4, 5) arrA.zipAll(arrB, 0, 0).map(x => x._1 + x._2) 

或者在Kotlin中做到这一点的正确方法是什么?

Kotlin 1.0中没有内置的模拟器。 将它添加到stdlib可能是一个好主意。 随意在YouTrack上提出问题

为了好玩,我做了一个快速的尾递归版本。 虽然不是非常有效,但由于列表附加。

 fun <T, U> List<T>.zipAll(that: List<U>, elem1: T, elem2: U): List<Pair<T, U>> { tailrec fun helper(first: List<T>, second: List<U>, acc: List<Pair<T, U>>): List<Pair<T, U>> { return when { first.isEmpty() && second.isEmpty() -> acc first.isEmpty() -> helper(first, second.drop(1), acc + listOf(elem1 to second.first())) second.isEmpty() -> helper(first.drop(1), second, acc + listOf(first.first() to elem2)) else -> helper(first.drop(1), second.drop(1), acc + listOf(first.first() to second.first())) } } return helper(this, that, emptyList()) } 

这里是Kotlin的zipAll

 fun <T1: Any, T2: Any> List<T1>.zipAll(other: List<T2>, emptyValue: T1, otherEmptyValue: T2): List<Pair<T1, T2>> { val i1 = this.iterator() val i2 = other.iterator() return generateSequence { if (i1.hasNext() || i2.hasNext()) { Pair(if (i1.hasNext()) i1.next() else emptyValue, if (i2.hasNext()) i2.next() else otherEmptyValue) } else { null } }.toList() } 

而一个单元测试:

 @Test fun sumTwoUnevenLists() { val x = listOf(1,2,3,4,5) val y = listOf(10,20,30) assertEquals(listOf(11,22,33,4,5), x.zipAll(y, 0, 0).map { it.first + it.second }) } 

同样可以应用于数组,其他集合类型,序列等。由于您可以索引到数组中,因此只有数组的版本会更容易。 阵列版本可能是:

 fun <T1: Any, T2: Any> Array<T1>.zipAll(other: Array<T2>, emptyValue: T1, otherEmptyValue: T2): List<Pair<T1, T2>> { val largest = this.size.coerceAtLeast(other.size) val result = arrayListOf<Pair<T1, T2>>() (0..this.size.coerceAtLeast(other.size)-1).forEach { i -> result.add(Pair(if (i < this.size) this[i] else emptyValue, if (i < other.size) other[i] else otherEmptyValue)) } return result.filterNotNull() } 

它返回一个List因为map函数会把你变成一个列表。