разреженный список значений с использованием диапазонов

есть более строгий способ написания

listOf('a'..'z','A'..'Z').flatMap { it }

Идея здесь состоит в том, чтобы перебирать некоторые значения в диапазоне, например числа от 1 до 100, пропуская с 21 по 24

listOf(1..20, 25..100).flatMap { it }

Ответ 1

Вы можете пойти немного короче для списка, используя flatten() вместо flatMap():

listOf('a'..'z','A'..'Z').flatten()

или более короткая форма (из @Ilya) - использовать оператор plus() + для Iterable (интерфейс, который реализует диапазоны). Каждая + сделает копию списка:

val validLetters = ('a'..'z') + ('A'..'Z')
val someNumbers = (1..20) + (25..100)

или пойти более ленивым, как Sequence (не уверен, что это имеет значение здесь вообще, чтобы быть более ленивым):

sequenceOf('a'..'z','A'..'Z').flatten()

Как вспомогательные функции

В Котлине люди обычно создают вспомогательную функцию, чтобы хорошо обернуть такие вещи; если вам посчастливилось повторно использовать этот код:

// helper functions
fun sparseListOf(vararg ranges: CharRange): List<Char> = ranges.flatMap { it }       
fun sparseListOf(vararg ranges: IntRange): List<Int> = ranges.flatMap { it }

... и использование для этих помощников:

val validLetters = sparseListOf('a'..'z', 'A'..'Z')
val someNumbers = spareListOf(1..20, 25..100)

ПРИМЕЧАНИЕ: вспомогательные функции используют flatMap(), так как нет flatten() метода или расширения для Array<out XYZ> который является типом получил от vararg. Лямбда встроена настолько, что нет никакой реальной разницы в производительности.

Ответ 2

kotlin.Char.rangeTo возвращает CharRange который является реализацией CharProgression. CharProgression является подклассом Iterable а оператор "плюс" определяется на итерациях: Iterable<T>.plus

Похоже на очень простое и очевидное

('a'..'z') + ('A'..'Z')