- Kotlin Ranges
- Kotlin range creation
- Kotlin range of characters
- Kotlin range forEach
- Kotlin range iterator
- Kotlin range step
- Kotlin range filter, reduce, map
- Kotlin range min, max, sum, average
- Диапазоны и прогрессии
- Диапазоны
- Прогрессии
- How to Use Kotlin Range Expressions
- 1. Introduction
- 2. Using Kotlin Ranges
- 2.1. Creating Ranges
- 2.2. Iterating Ranges
- 3. Using the step() Function
- 4. Using the reversed() Function
- 5. Using the until() Function
- 6. The last, first, step Elements
- 7. Filtering Ranges
- 8. Other Utility Functions
- 9. Custom Objects
- 10. Conclusion
Kotlin Ranges
Kotlin Ranges tutorial shows how to work with ranges in Kotlin.
A range is a succession of values between defined lower and upper limits.
A Kotlin range is created with the .. operator or with the rangeTo and downTo functions. Kotlin ranges are inclusive by default; that is, 1..3 creates a range of 1, 2, 3 values. The distance between two values is defined by the step; the default step is 1.
Kotlin range creation
The following example shows how to create simple ranges in Kotlin.
package com.zetcode fun main()
The example creates four ranges of values.
The 1..30 creates a succession of values from 1 to 30, including the bounds. We use the for loop to go through the range.
for (i in 30 downTo 1) print("$i ")
With the downTo keyword, we create a succession of values descending from 30 to 1.
for (i in 1.rangeTo(30)) print("$i ")
The rangeTo function creates a range of values between the defined bounds; it is an equivalent of the .. operator.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Kotlin range of characters
We can create a range of characters in Kotlin.
package com.zetcode fun main()
The example creates two ranges of letters in ascending and descending orders.
We create and print ‘a’ to ‘k’ characters.
for (c in 'k' downTo 'a') print("$c ")
We create and print ‘k’ to ‘a’ characters.
a b c d e f g h i j k k j i h g f e d c b a
Kotlin range forEach
We can use the forEach function to traverse the range of values.
package com.zetcode fun main() < (1..5).forEach(::println) (1..5).reversed().forEach < e ->print("$e ") > >
The example uses the forEach function to traverse the ranges.
With the forEach function, we print all the values from range 1..5 .
In this line, we reverse the range with reversed and loop over the range with forEach .
Kotlin range iterator
We can use the classic iterator to loop over a range in Kotlin.
package com.zetcode fun main() < val chars = ('a'..'f') val it = chars.iterator() while (it.hasNext()) < val e = it.next() println(e) >>
The example uses an iterator to loop over a range of characters.
val chars = ('a'..'f') val it = chars.iterator()
We create a range of characters and an iterator from this range.
In a while loop, we go over the elements of the range. The hasNext method checks if there is a next element in the range and the next method returns the next element in the range.
Kotlin range step
With the step keyword, we can define a step between the values of a range.
package com.zetcode fun main() < for (e in 1..20 step 2) < print("$e ") >println() for (e in 1..20 step 5) < print("$e ") >println() println((1..10 step 2).last) println((1..10 step 3).first) println((1..10 step 4).step) println() >
The example shows how to use step in Kotlin ranges.
The for loop goes through the values of a range. The range has step 2.
println((1..10 step 2).last) println((1..10 step 3).first) println((1..10 step 4).step)
A Kotlin range contains last , first , and step attributes, which return the last, first values and the step.
1 3 5 7 9 11 13 15 17 19 1 6 11 16 9 1 4
Kotlin range filter, reduce, map
Kotlin ranges contain filter, reduce, and map operations.
package com.zetcode fun main() < val rnums = (1..15) println(rnums) val r = rnums.filter < e ->e % 2 == 0 > println(r) val r2 = rnums.reduce < total, next ->next * 2 - 1 > println(r2) var r3 = rnums.map < e ->e * 5 > println(r3) >
The example applies filtering, reduction, and mapping on a range.
val r = rnums.filter < e ->e % 2 == 0 >
With the filter function we filter out even numbers. Even numbers can be divided by two without a remainder. The operation returns a list of values.
val r2 = rnums.reduce < total, next ->next * 2 - 1 >
The reduction operation applies the given expression on each of the range elements to produce a single value.
The mapping operation applies the given operation on each of the elements. The mapping returns a list of modified values.
1..15 [2, 4, 6, 8, 10, 12, 14] 29 [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75]
Kotlin range min, max, sum, average
Kotlin ranges contain predefined reduction operations, including min , max , sum , and average
package com.zetcode fun main()
The example prints the minimum, maximum, summation, and average of a range of 1..10 values.
In this tutorial, we have covered Kotlin ranges.
Диапазоны и прогрессии
Kotlin позволяет легко создавать диапазоны значений с помощью функции rangeTo() , которая находится в пакете kotlin.ranges . У функции есть операторная форма — .. . Обычно rangeTo() используется совместно с функциями in или !in .
У диапазонов целочисленных типов ( IntRange , LongRange , CharRange ) есть дополнительная функция: они поддерживают итерацию. Эти диапазоны также являются прогрессиями.
Подобные диапазоны, как правило, используются в цикле for .
Для перебора чисел в обратном порядке используйте функцию downTo вместо .. .
Можно перебирать числа с произвольным шагом. Осуществляется это с помощью функции step .
Если требуется перебрать диапазон чисел, исключая его последний элемент, то используйте функцию until .
Диапазоны
В математическом смысле диапазон — это закрытый интервал: он определяется двумя значениями и они оба являются частью диапазона. Диапазоны применимы к сопоставимым (comparable) типам: имея порядок, вы можете определить, находится ли произвольный экземпляр в диапазоне между двумя заданными экземплярами.
Основная операция с диапазонами — это contains , которая обычно используется в форме операторов in и !in .
Чтобы создать диапазон на основе ваших классов, вызовите функцию rangeTo() для начального значения диапазона и укажите конечное значение в качестве аргумента. Чаще всего используется операторная форма функции rangeTo() — .. .
class Version(val major: Int, val minor: Int): Comparable < override fun compareTo(other: Version): Int < if (this.major != other.major) < return this.major - other.major >return this.minor - other.minor > > fun main() < val versionRange = Version(1, 11)..Version(1, 30) println(Version(0, 9) in versionRange) // false println(Version(1, 20) in versionRange) // true >
Прогрессии
Как показано в приведённых выше примерах, диапазоны целочисленных типов, таких как Int , Long и Char , можно рассматривать как арифметические прогрессии. В Kotlin есть специальные типы для определения таких прогрессий: IntProgression , LongProgression и CharProgression .
У прогрессий есть три основных свойства: first , last и step , при этом step не может быть нулём. first — это первый элемент. Последующие элементы — это предыдущий элемент плюс step . Итерация по прогрессии с положительным шагом ( step ) эквивалентна индексируемому циклу for в Java / JavaScript.
При неявном создании прогрессии путём итерации диапазона, элементы first и last этой прогрессии являются конечными точками диапазона, а step равен 1.
Чтобы прогрессии задать собственный шаг, используйте функцию step .
Последний элемент прогрессии ( last ) рассчитывается следующим образом:
- Для положительного шага: максимальное значение, но не больше конечного значения — (last — first) % step == 0 .
- Для отрицательного шага: минимальное значение, но не меньше конечного значения — (last — first) % step == 0 .
Таким образом, элемент last не всегда совпадает с конечным значением диапазона.
Чтобы создать прогрессию для итерации в обратном направлении, при определении диапазона используйте downTo вместо .. .
`, where `N` is `Int`, `Long`, or `Char` respectively, so you can use them in various [collection functions](collection-operations.md) like `map`, `filter`, and other. —>
Прогрессии реализуют интерфейс Iterable , где N — это Int , Long или Char , поэтому вы можете использовать их в различных функциях коллекций, таких как map , filter и т. д.
How to Use Kotlin Range Expressions
As a seasoned developer, you’re likely already familiar with Spring. But Kotlin can take your developer experience with Spring to the next level!
- Add new functionality to existing classes with Kotlin extension functions.
- Use Kotlin bean definition DSL.
- Better configure your application using lateinit.
- Use sequences and default argument values to write more expressive code.
By the end of this talk, you’ll have a deeper understanding of the advanced Kotlin techniques that are available to you as a Spring developer, and be able to use them effectively in your projects.
1. Introduction
A range is a sequence of values defined by a start, an end, and a step.
In this quick tutorial, we’ll have a look at how we can define and use ranges in Kotlin.
2. Using Kotlin Ranges
In Kotlin, we can create ranges using the rangeTo() and downTo() functions or the .. operator.
We can use ranges for any comparable type.
By default, they’re inclusive, which means that the 1..4 expression corresponds to the values 1,2,3 and 4.
In addition, there’s another default: the distance between two values, called a step, with an implicit value of 1.
So now, let’s take a look at a few examples of creating ranges and using other useful methods to manipulate them.
2.1. Creating Ranges
Ranges implement a common interface – ClosedRange. The result of a ClosedRange is a progression (such as IntProgression, LongProgression, or CharProgression).
This progression contains a start, an inclusive end, and a step and it’s a subtype of Iterable where N is Int, Long or Char.
Let’s start by looking at the simplest way to create a range, using the “..” and in operators:
Also, if we want to define a backward range we can use the downTo operator:
We can also use this expression as part of an if statement to check if a value belongs to a range:
2.2. Iterating Ranges
Now, while we can use ranges with anything comparable, if we want to iterate, then we need an integral type range.
Now let’s take a look at the code to iterate through a range:
for (i in 1.rangeTo(9)) < print(i) // Print 123456789 >for (i in 9.downTo(1)) < print(i) // Print 987654321 >
The same use case applies to chars:
for (ch in 'a'..'f') < print(ch) // Print abcdef >for (ch in 'f' downTo 'a') < print(ch) // Print fedcba >
3. Using the step() Function
The use of the step() function is fairly intuitive: we can use it to define a distance between the values of the range:
for(i in 1..9 step 2) < print(i) // Print 13579 >for (i in 9 downTo 1 step 2) < print(i) // Print 97531 >
In this example, we’re iterating forward and backward through the values from 1-9, with a step value of 2.
4. Using the reversed() Function
As the name suggests, the reversed() function will reverse the order of the range:
(1..9).reversed().forEach < print(it) // Print 987654321 >(1..9).reversed().step(3).forEach < print(it) // Print 963 >
5. Using the until() Function
When we want to create a range that excludes the end element we can use until():
6. The last, first, step Elements
If we need to find the first, the step or the last value of the range, there are functions that will return them to us:
print((1..9).first) // Print 1 print((1..9 step 2).step) // Print 2 print((3..9).reversed().last) // Print 3
7. Filtering Ranges
The filter() function will return a list of elements matching a given predicate:
val r = 1..10 val f = r.filter < it ->it % 2 == 0 > // Print [2, 4, 6, 8, 10]
We can also apply other functions such as map() and reduce() to our range:
val m = r.map < it ->it * it > // Print [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] val rdc = r.reduce a + b> // Print 55
8. Other Utility Functions
There are many other functions we can apply to our range, like min, max, sum, average, count, distinct:
val r = 1..20 print(r.min()) // Print 1 print(r.max()) // Print 20 print(r.sum()) // Print 210 print(r.average()) // Print 10.5 print(r.count()) // Print 20 val repeated = listOf(1, 1, 2, 4, 4, 6, 10) print(repeated.distinct()) // Print [1, 2, 4, 6, 10]
9. Custom Objects
It’s also possible to create a range over custom objects. For that, the only requirement is to extend the Comparable interface.
An enum is a good example. All enums in Kotlin extend Comparable which means that, by default, the elements are sorted in the sequence they appear.
Let’s create a quick Color enum:
enum class Color(val rgb: Int) : Comparable
And then use it in some if statements:
val range = red..yellow if (range.contains(Color.MAGENTA)) println("true") // Print true if (Color.RED in Color.GREEN..Color.YELLOW) println("true") // Print true if (Color.RED !in Color.MAGENTA..Color.YELLOW) println("true") // Print true
However, as this is not an integral type, we can’t iterate over it. If we try, we’ll get a compilation error:
And if we do want to have a custom range that we can iterate over, we just need to implement ClosedRange as well as Iterator.
10. Conclusion
In this article, we demonstrated how we can use range expressions in Kotlin and different functions we can apply.
As always the source code is available over on GitHub.