'sparse list of values using ranges

is there a more terse way of writing

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

The idea here is to iterate over some values in a range, like the numbers from 1 through 100, skipping 21 through 24

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


Solution 1:[1]

You can go slightly shorter for a list by using flatten() instead of flatMap():

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

or a shorter form (from @Ilya) is to use the plus() + operator of Iterable (an interface that ranges implement). Each + will make a copy of the list:

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

or go more lazy as a Sequence (not sure it matters here at all to be lazier):

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

##As Helper Functions##

In Kotlin people typically create a helper function to wrap things like this up nicely; if you happen to re-use this code a lot:

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

...and the usage for those helpers:

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

NOTE: the helper functions use flatMap() since there is no flatten() method or extension for Array<out XYZ> which is the type received from the vararg. The lambda is inlined so likely there is no real difference in performance.

Solution 2:[2]

The kotlin.Char.rangeTo returns a CharRange that is an implementation of CharProgression. CharProgression is a subclass of Iterable and the plus operator is defined on iterables: Iterable<T>.plus

Yeilding a very simple looking and obvious

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 activedecay