Aprendizado Kotlin - Alguns recursos da linguagem - Ranges

01 May 2020 » kotlin (aproximadamente 7 minutos de leitura)


Conheça a série sobre Kotlin

Introdução

Continuando aprendizado e descoberta sobre Kotlin. Falaremos sobre Ranges.

Recursos da linguagens observadores e experimentados

Nessa seção, pretendo falar de alguns recursos que pude experimentar durante o curso, e pratiquei em um projeto piloto que está disponível em um repositório no meu github onde pretendo colocar os demos do que ando testando com Kotlin. Esse repositório é o kotlin-lab.

Ranges

Kotlin tem um mecanismo que lida com intervalos chamado Range. Um range define um intervalo fechado entre dois pontos e os pontos são incluídos nesse intervalo. Eles são definidos por tipos comparáveis que possuem critério de ordem. Qualquer classe que implemente a interface Comparable pode criar um Range. Um uso muito comum é para intervalos númericos, datas e textos. Alguns exemplos seguem abaixo:

val start = Date.valueOf("2017-01-01")
val end = Date.valueOf("2017-12-31")
val range = start..end
println(range) // 2017-01-01..2017-12-31

println("Date.valueOf("2017-05-27") in range is ${Date.valueOf("2017-05-27") in range}") // true
println("Date.valueOf("2018-01-01") in range is ${Date.valueOf("2018-01-01") in range}") // false
println("Date.valueOf("2018-01-01") !in range is \${Date.valueOf("2018-01-01") !in range}") // true

val range = 1.0..100.0
println(range) // 1.0..100.0

println("3.14 in range is ${3.14 in range}") // true
println("100.1 in range is ${100.1 in range}") // false

val range = 1f..100f
println(range) // 1.0..100.0

println("3.14f in range is ${3.14f in range}") // true
println("100.1f in range is ${100.1f in range}") // false

Para utilização de ranges é necessário seguir a seguinte sintaxe inicioRange..fimRange. Para testes condicionais é possível utilizar as funções in e !in. Ranges númericos ((IntRange, LongRange, CharRange) tem um recurso adicional que eles podem ser iterados. Esses ranges também são progressões (uma sequência numérica que a diferença entre os números tem uma valor constante).

Para iterar na ordem reversa os números, existe a função downTo ao invés de .., como mostra o exemplo abaixo:

for (i in 1..4) print(i) //1,2,3,4
for (i in 4 downTo 1) print(i) //4,3,2,1

É possível definir também o salto (o padrão é um) para uma iteração de um range, usando a sintaxe step.

for (i in 1..8 step 2) print(i)
println()
for (i in 8 downTo 1 step 2) print(i)

Como podemos observar no exemplo acima, os intervalos de um range são inclusivos. Caso queira excluir o último elemento deve ser usado a função until, como no exemplo abaixo:

for (i in 1 until 10) { // i in [1, 10), 10 is excluded
print(i)
}

Exemplo de range de characteres:

    for (c in 'a'..'k')
        print("$c ")

    println()

    for (c in 'k' downTo 'a')
        print("$c ")

print(i)
}

forEach e iterator

Para iterar um range também existe a possibilidade de utilizar um forEach ou usar um iterator, como no exemplo abaixo:

(1..5).forEach(::println)

    (1..5).reversed().forEach { e -> print("$e ") }

    val chars = ('a'..'f') //usando range como variável.

val it = chars.iterator()

    

Range suporta operações filter, reduce e map

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)

Range possui operações pre-definidas de min, max, sum,count, average, distinct

val r = (1..10)

    println(r.min())
    println(r.max())
    println(r.sum())
    println(r.average())
    println(r.count())

    val repeated = listOf(1, 1, 2, 4, 4, 6, 10)

print(repeated.distinct()) // Print [1, 2, 4, 6, 10]

    

Função reversed para iteração em ordem reversa

(1..9).reversed().forEach {
print(it) // Print 987654321
}

(1..9).reversed().step(3).forEach {
print(it) // Print 963
}

Encontrar primeiro, último e step.

print((1..9).first) // Print 1
print((1..9 step 2).step) // Print 2
print((3..9).reversed().last) // Print 3

Qualquer objeto pode ser colocado como Range, desde que implemente a interface Comparable

enum class Color(val rgb: Int) : Comparable<Color> {
BLUE(0x0000FF),
GREEN(0x008000),
RED(0xFF0000),
MAGENTA(0xFF00FF),
YELLOW(0xFFFF00);
}

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

fun main(args: Array<String>) {
for (c in Color.BLUE.rangeTo(Color.YELLOW)) println(c) // for-loop range must have an iterator() method
}

Conclusão

Nos dois links abaixo é possível brincar um pouco online com ranges em Kotlin. A documentação da linguagem também é auto-explicativa e provê muitos recursos.

Nesse estudo, apresentei alguns recursos do Kotlin que são bastante inovadores para mim que vim da linguagem Java. Espero continuar aprendendo.


Conheça a série sobre Kotlin

Outras Fontes:

  • https://kotlinlang.org/docs/reference/ranges.html
  • https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/range-to.html
  • https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/-int-range/
  • https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/-long-range/
  • https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/-char-range/
  • http://zetcode.com/kotlin/ranges/
  • https://www.baeldung.com/kotlin-ranges
  • https://www.geeksforgeeks.org/kotlin-ranges/
  • https://beginnersbook.com/2019/02/kotlin-ranges/


Conheça a série sobre Kotlin