Вопрос:

Как мне бесконечно повторить последовательность в Kotlin?

collections kotlin sequence

1744 просмотра

5 ответа

1698 Репутация автора

Я хочу бесконечно повторять Tэлементы в Sequence<T>. Это не может быть сделано с помощью kotlin.collections.asSequence . Например:

val intArray = intArrayOf(1, 2, 3)
val finiteIntSequence = intArray.asSequence()
val many = 10
finiteIntSequence.take(many).forEach(::print)
// 123

Это не то, что я хочу. Я ожидал, что какая-то kotlin.collections.repeatфункция существует, но ее нет, поэтому я сам ее реализовал (например, для этого IntArray):

var i = 0
val infiniteIntSequence = generateSequence { intArray[i++ % intArray.size] }
infiniteIntSequence.take(many).forEach(::print)
// 1231231231

Это совершенно необходимо, поэтому я считаю, что должен быть более функциональный и менее многословный способ сделать это. Если он существует, каков / является стандартный способ (ы) Kotlin для повторения коллекций / массивов a (n) (in) конечное количество раз?

Автор: Erik Источник Размещён: 28.12.2017 12:12

Ответы (5)


1 плюс

33778 Репутация автора

Я думаю, что это довольно ясно:

generateSequence(0) { (it + 1) % intArray.size }
        .map { intArray[it] }
        .forEach { println(it) }
Автор: s1m0nw1 Размещён: 28.12.2017 12:28

10 плюса

6016 Репутация автора

Решение

Обновление: сопрограммы больше не являются экспериментальными с Kotlin 1.3! Используйте их сколько хотите :)


Если вы разрешите использование сопрограмм, вы можете сделать это довольно чисто, используя sequence:

бесконечное количество раз

fun <T> Sequence<T>.repeat() = sequence { while (true) yieldAll(this@repeat) }

Обратите внимание на использование квалифицированного thisвыражения this@repeat - простое использование thisотносится к лямбда-получателю, a SequenceScope.

тогда вы можете сделать

val intArray = intArrayOf(1, 2, 3)
val finiteIntSequence = intArray.asSequence()
val infiniteIntSequence = finiteIntSequence.repeat()

println(infiniteIntSequence.take(10).toList())
// ^ [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]

конечное количество раз

fun <T> Sequence<T>.repeat(n: Int) = sequence { repeat(n) { yieldAll(this@repeat) } }
Автор: Moira Размещён: 28.12.2017 12:31

1 плюс

33778 Репутация автора

Типичным решением было бы повторно использовать предложение из этого ответа с функциями расширения:

fun <T> Array<T>.asRepeatedSequence() =
        generateSequence(0) {
            (it + 1) % this.size
        }.map(::get)

fun <T> List<T>.asRepeatedSequence() =
        generateSequence(0) {
            (it + 1) % this.size
        }.map(::get)

Вызывается так:

intArray.asRepeatedSequence().forEach(::println)
Автор: s1m0nw1 Размещён: 28.12.2017 01:50

4 плюса

1698 Репутация автора

Чтобы избежать использования экспериментальных сопрограмм, используйте:

generateSequence { setOf("foo", 'b', 'a', 'r') }
  .flatten() // Put the Iterables' contents into one Sequence
  .take(5) // Take 5 elements
  .joinToString(", ")

// Result: "foo, b, a, r, foo"

или, в качестве альтернативы, если вы хотите повторить всю коллекцию несколько раз, просто возьмите перед выравниванием:

generateSequence { setOf("foo", 'b', 'a', 'r') }
  .take(5) // Take the entire Iterable 5 times
  .flatten() // Put the Iterables' contents into one Sequence
  .joinToString(", ")

// Result: "foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r"

Для исходного вопроса IntArrayмассив сначала должен быть преобразован в Iterable<Int>(иначе flatten()недоступно):

val intArray = intArrayOf(1, 2, 3)

generateSequence { intArray.asIterable() }
  .flatten()
  .take(10)
  .joinToString(", ")

// Result: "1, 2, 3, 1, 2, 3, 1, 2, 3, 1"

Кроме того, другие типы Array, например, ByteArrayили LongArray, а также Mapнет Iterable, но все они реализуют asIterable()способ, как IntArrayв примере выше.

Автор: Erik Размещён: 29.12.2017 02:33

0 плюса

10246 Репутация автора

Я не уверен, связано ли это с изменениями API в Kotlin, но возможно сделать следующее:

fun <T> Sequence<T>.repeatForever() =
  generateSequence(this) { it }.flatten()

Живой пример: https://pl.kotl.in/W-h1dnCFx

Автор: pablisco Размещён: 08.05.2019 10:08
Вопросы из категории :
32x32