Introduce 'pairwise' function, KEEP-11
This commit is contained in:
@@ -924,6 +924,12 @@ public expect operator fun <T> Iterable<T>.minus(elements: Sequence<T>): List<T>
|
||||
@kotlin.internal.InlineOnly
|
||||
public expect inline fun <T> Iterable<T>.minusElement(element: T): List<T>
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun <T> Iterable<T>.pairwise(): List<Pair<T, T>>
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public expect inline fun <T, R> Iterable<T>.pairwise(transform: (a: T, b: T) -> R): List<R>
|
||||
|
||||
/**
|
||||
* Splits the original collection into pair of lists,
|
||||
* where *first* list contains elements for which [predicate] yielded `true`,
|
||||
|
||||
@@ -848,6 +848,12 @@ public expect operator fun <T> Sequence<T>.minus(elements: Sequence<T>): Sequenc
|
||||
@kotlin.internal.InlineOnly
|
||||
public expect inline fun <T> Sequence<T>.minusElement(element: T): Sequence<T>
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun <T> Sequence<T>.pairwise(): Sequence<Pair<T, T>>
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun <T, R> Sequence<T>.pairwise(transform: (a: T, b: T) -> R): Sequence<R>
|
||||
|
||||
/**
|
||||
* Splits the original sequence into pair of lists,
|
||||
* where *first* list contains elements for which [predicate] yielded `true`,
|
||||
|
||||
@@ -638,6 +638,12 @@ public expect inline fun CharSequence.sumBy(selector: (Char) -> Int): Int
|
||||
*/
|
||||
public expect inline fun CharSequence.sumByDouble(selector: (Char) -> Double): Double
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun CharSequence.pairwise(): List<Pair<Char, Char>>
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public expect inline fun <R> CharSequence.pairwise(transform: (a: Char, b: Char) -> R): List<R>
|
||||
|
||||
/**
|
||||
* Splits the original char sequence into pair of char sequences,
|
||||
* where *first* char sequence contains characters for which [predicate] yielded `true`,
|
||||
|
||||
@@ -1844,6 +1844,25 @@ public inline fun <T> Iterable<T>.minusElement(element: T): List<T> {
|
||||
return minus(element)
|
||||
}
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public fun <T> Iterable<T>.pairwise(): List<Pair<T, T>> {
|
||||
return pairwise { a, b -> a to b }
|
||||
}
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public inline fun <T, R> Iterable<T>.pairwise(transform: (a: T, b: T) -> R): List<R> {
|
||||
val iterator = iterator()
|
||||
if (!iterator.hasNext()) return emptyList()
|
||||
val result = mutableListOf<R>()
|
||||
var current = iterator.next()
|
||||
while (iterator.hasNext()) {
|
||||
val next = iterator.next()
|
||||
result.add(transform(current, next))
|
||||
current = next
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the original collection into pair of lists,
|
||||
* where *first* list contains elements for which [predicate] yielded `true`,
|
||||
|
||||
@@ -1413,6 +1413,25 @@ public inline fun <T> Sequence<T>.minusElement(element: T): Sequence<T> {
|
||||
return minus(element)
|
||||
}
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public fun <T> Sequence<T>.pairwise(): Sequence<Pair<T, T>> {
|
||||
return pairwise { a, b -> a to b }
|
||||
}
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public fun <T, R> Sequence<T>.pairwise(transform: (a: T, b: T) -> R): Sequence<R> {
|
||||
return buildSequence result@ {
|
||||
val iterator = iterator()
|
||||
if (!iterator.hasNext()) return@result
|
||||
var current = iterator.next()
|
||||
while (iterator.hasNext()) {
|
||||
val next = iterator.next()
|
||||
yield(transform(current, next))
|
||||
current = next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the original sequence into pair of lists,
|
||||
* where *first* list contains elements for which [predicate] yielded `true`,
|
||||
|
||||
@@ -1110,6 +1110,22 @@ public inline fun CharSequence.sumByDouble(selector: (Char) -> Double): Double {
|
||||
return sum
|
||||
}
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public fun CharSequence.pairwise(): List<Pair<Char, Char>> {
|
||||
return pairwise { a, b -> a to b }
|
||||
}
|
||||
|
||||
@SinceKotlin("1.2")
|
||||
public inline fun <R> CharSequence.pairwise(transform: (a: Char, b: Char) -> R): List<R> {
|
||||
val size = length - 1
|
||||
if (size < 1) return emptyList()
|
||||
val result = ArrayList<R>(size)
|
||||
for (index in 0..size - 1) {
|
||||
result.add(transform(this[index], this[index + 1]))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the original char sequence into pair of char sequences,
|
||||
* where *first* char sequence contains characters for which [predicate] yielded `true`,
|
||||
|
||||
@@ -116,6 +116,25 @@ abstract class OrderedIterableTests<T : Iterable<String>>(createFrom: (Array<out
|
||||
expect(null) { empty.lastOrNull() }
|
||||
expect("foo") { data.lastOrNull { it.startsWith("f") } }
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun pairwise() {
|
||||
val data = createFrom("", "a", "xyz")
|
||||
val lengthDeltas = data.pairwise { a, b -> b.length - a.length }
|
||||
assertEquals(listOf(1, 2), lengthDeltas)
|
||||
|
||||
assertTrue(empty.pairwise { a, b -> a + b }.isEmpty())
|
||||
assertTrue(createFrom("foo").pairwise { a, b -> a + b }.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun pairwisePairs() {
|
||||
assertTrue(empty.pairwise().isEmpty())
|
||||
assertTrue(createFrom("foo").pairwise().isEmpty())
|
||||
assertEquals(listOf("a" to "b"), createFrom("a", "b").pairwise())
|
||||
assertEquals(listOf("a" to "b", "b" to "c"), createFrom("a", "b", "c").pairwise())
|
||||
}
|
||||
}
|
||||
|
||||
abstract class IterableTests<T : Iterable<String>>(val createFrom: (Array<out String>) -> T, val empty: T) {
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package test.collections
|
||||
|
||||
import org.junit.Test
|
||||
@@ -12,6 +28,22 @@ fun fibonacci(): Sequence<Int> {
|
||||
|
||||
public class SequenceTest {
|
||||
|
||||
private class TriggerSequence<out T>(val source: Sequence<T>) : Sequence<T> {
|
||||
var iterated: Boolean = false
|
||||
private set
|
||||
|
||||
override fun iterator(): Iterator<T> = source.iterator().also { iterated = true }
|
||||
}
|
||||
|
||||
fun <T> ensureIsIntermediate(source: Sequence<T>, operation: (Sequence<T>) -> Sequence<*>) {
|
||||
TriggerSequence(source).let { s ->
|
||||
val result = operation(s)
|
||||
assertFalse(s.iterated, "Source should not be iterated before the result is")
|
||||
result.iterator().hasNext()
|
||||
assertTrue(s.iterated, "Source should be iterated after the result is iterated")
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun filterEmptySequence() {
|
||||
for (sequence in listOf(emptySequence<String>(), sequenceOf<String>())) {
|
||||
assertEquals(0, sequence.filter { false }.count())
|
||||
@@ -165,6 +197,25 @@ public class SequenceTest {
|
||||
assertEquals("", sequenceOf(1).dropWhile { it < 200 }.joinToString(limit = 10))
|
||||
}
|
||||
|
||||
@Test fun pairwise() {
|
||||
val deltas = fibonacci().pairwise { a, b -> b - a }
|
||||
// deltas of 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...
|
||||
// is the same sequence prepended by 1
|
||||
assertEquals(listOf(1) + fibonacci().take(9), deltas.take(10).toList())
|
||||
|
||||
ensureIsIntermediate(source = sequenceOf(1, 2)) { it.pairwise { a, b -> b - a } }
|
||||
}
|
||||
|
||||
@Test fun pairwisePairs() {
|
||||
val pairs: Sequence<Pair<String, String>> = sequenceOf("a", "b", "c", "d").pairwise()
|
||||
assertEquals(listOf("a" to "b", "b" to "c", "c" to "d"), pairs.toList())
|
||||
|
||||
assertTrue(emptySequence<String>().pairwise().toList().isEmpty())
|
||||
assertTrue(sequenceOf(1).pairwise().toList().isEmpty())
|
||||
|
||||
ensureIsIntermediate(source = sequenceOf(1, 2)) { it.pairwise() }
|
||||
}
|
||||
|
||||
@Test fun zip() {
|
||||
expect(listOf("ab", "bc", "cd")) {
|
||||
sequenceOf("a", "b", "c").zip(sequenceOf("b", "c", "d")) { a, b -> a + b }.toList()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -837,6 +837,18 @@ class StringTest {
|
||||
assertContentEquals("abc", pair.second, "pair.second")
|
||||
}
|
||||
|
||||
@Test fun pairwise() = withOneCharSequenceArg { arg1 ->
|
||||
assertEquals(listOf("ab", "bc"), arg1("abc").pairwise { a, b -> a.toString() + b })
|
||||
assertTrue(arg1("").pairwise { a, b -> a.toString() + b }.isEmpty())
|
||||
assertTrue(arg1("a").pairwise { a, b -> a.toString() + b }.isEmpty())
|
||||
}
|
||||
|
||||
@Test fun pairwisePairs() = withOneCharSequenceArg { arg1 ->
|
||||
assertEquals(listOf('a' to 'b', 'b' to 'c'), arg1("abc").pairwise())
|
||||
assertTrue(arg1("").pairwise().isEmpty())
|
||||
assertTrue(arg1("a").pairwise().isEmpty())
|
||||
}
|
||||
|
||||
@Test fun map() = withOneCharSequenceArg { arg1 ->
|
||||
assertEquals(listOf('a', 'b', 'c'), arg1("abc").map { it })
|
||||
|
||||
|
||||
Reference in New Issue
Block a user