Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 1036 Vote(s) - 3.56 Average
  • 1
  • 2
  • 3
  • 4
  • 5
What is the equivalent of Python list, set, and map comprehensions in Kotlin?

#1
In Python, there are list comprehensions and similar constructs for maps and sets. In Kotlin there is nothing at all in any of the documentation with a similar name.

What are the equivalents of these comprehensions? For example, those found in [Python 3 Patterns, Recipes and Idioms](

[To see links please register here]

). Which includes comprehensions for:

* list
* set
* dictionary

***Note:*** *this question is intentionally written and answered by the author ([Self-Answered Questions](

[To see links please register here]

)), so that the idiomatic answers to commonly asked Kotlin topics are present in SO.*
Reply

#2
Taking examples from [Python 3 Patterns, Recipes and Idioms](

[To see links please register here]

) we can convert each one to Kotlin using a simple pattern. The Python version of a list comprehension has 3 parts:

1. output expression
2. input list/sequence and variable
3. optional predicate

These directly correlate to Kotlin functional extensions to collection classes. The input sequence, followed by the optional predicate in a `filter` lambda, followed by the output expression in a `map` lambda. So for this Python example:

<!-- language: python -->

# === PYTHON

a_list = [1, 2, 3, 4, 5, 6]

# output | var | input | filter/predicate
even_ints_squared = [ e*e for e in a_list if e % 2 == 0 ]

print(even_ints_squared)
# output: [ 4, 16, 36 ]

Becomes

<!-- language: kotlin -->

// === KOTLIN

var aList = listOf(1, 2, 3, 4, 5, 6)

// input | filter | output
val evenIntsSquared = aList.filter { it % 2 == 0 }.map { it * it }

println(evenIntsSquared)
// output: [ 4, 16, 36 ]

Notice that the variable is not needed in the Kotlin version since the implied `it` variable is used within each lambda. In Python you can turn these into a lazy generator by using the `()` instead of square brackets:

<!-- language: python -->

# === PYTHON

even_ints_squared = ( e**2 for e in a_list if e % 2 == 0 )

And in Kotlin it is more obviously converted to a lazy sequence by changing the input via a function call `asSequence()`:

<!-- language: kotlin -->

// === KOTLIN

val evenIntsSquared = aList.asSequence().filter { it % 2 == 0 }.map { it * it }

<hr/>

Nested comprehensions in Kotlin are created by just nesting one within the other's `map` lambda. For example, take this sample from [PythonCourse.eu](

[To see links please register here]

) in Python changed slightly to use both a set and a list comprehension:

<!-- language: python -->

# === PYTHON

noprimes = {j for i in range(2, 8) for j in range(i*2, 100, i)}
primes = [x for x in range(2, 100) if x not in noprimes]
print(primes)
# output: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

Becomes:

<!-- language: kotlin -->

// === KOTLIN

val nonprimes = (2..7).flatMap { (it*2..99).step(it).toList() }.toSet()
val primes = (2..99).filterNot { it in nonprimes }
print(primes)
// output: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

Notice that the nested comprehension produces a list of lists which is converted to a flat list using `flatMap()` and then converted to a set using `toSet()`. Also, Kotlin ranges are inclusive, whereas a Python range is exclusive so you will see the numbers are slightly different in the ranges.

You can also use a `sequence` generator with co-routines in Kotlin to yield the values without needing the call to `flatMap()` or `flatten()`:

<!-- language: kotlin -->

// === KOTLIN

val nonprimes = sequence {
(2..7).forEach { (it*2..99).step(it).forEach { value -> yield(value) } }
}.toSet()
val primes = (2..99).filterNot { it in nonprimes }

<hr/>

Another example from the referenced Python page is generating a matrix:

<!-- language: python -->

# === PYTHON

matrix = [ [ 1 if item_idx == row_idx else 0 for item_idx in range(0, 3) ] for row_idx in range(0, 3) ]
print(matrix)
# [[1, 0, 0],
# [0, 1, 0],
# [0, 0, 1]]

And in Kotlin:

<!-- language: kotlin -->

// === KOTLIN

val matrix = (0..2).map { row -> (0..2).map { col -> if (col == row) 1 else 0 }}
println(matrix)
// [[1, 0, 0],
// [0, 1, 0],
// [0, 0, 1]]

Or in Kotlin instead of lists, you could also generate arrays:

<!-- language: kotlin -->

// === KOTLIN

val matrix2 = Array(3) { row ->
IntArray(3) { col -> if (col == row) 1 else 0 }
}

<hr/>

Another of the examples for set comprehensions is to generate a unique set of properly cased names:

<!-- language: python -->

# === PYTHON

names = [ 'Bob', 'JOHN', 'alice', 'bob', 'ALICE', 'J', 'Bob' ]

fixedNames = { name[0].upper() + name[1:].lower() for name in names if len(name) > 1 }

print(fixedNames)
# output: {'Bob', 'Alice', 'John'}

Is translated to Kotlin:

<!-- language: kotlin -->

// === KOTLIN

val names = listOf( "Bob", "JOHN", "alice", "bob", "ALICE", "J", "Bob" )

val fixedNames = names.filter { it.length > 1 }
.map { it.take(1).toUpperCase() + it.drop(1).toLowerCase() }
.toSet()

println(fixedNames)
// output: [Bob, John, Alice]

<hr/>

And the example for map comprehension is a bit odd, but can also be implemented in Kotlin. The original:

<!-- language: python -->

# === PYTHON

mcase = {'a':10, 'b': 34, 'A': 7, 'Z':3}

mcase_frequency = { k.lower() : mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys() }

print(mcase_frequency)
# output: {'a': 17, 'z': 3, 'b': 34}

And the converted, which is written to be a bit more "wordy" here to make it clearer what is happening:

<!-- language: kotlin -->

// === KOTLIN

val mcase = mapOf("a" to 10, "b" to 34, "A" to 7, "Z" to 3)

val mcaseFrequency = mcase.map { (key, _) ->
val newKey = key.toLowerCase()
val newValue = mcase.getOrDefault(key.toLowerCase(), 0) +
mcase.getOrDefault(key.toUpperCase(), 0)
newKey to newValue
}.toMap()

print(mcaseFrequency)
// output: {a=17, b=34, z=3}

<hr/>

Further reading:

* Kotlin adds more power than list/set/map comprehensions because of its extensive functional transforms that you can make to these collection types. See [What Java 8 Stream.collect equivalents are available in the standard Kotlin library?
](

[To see links please register here]

) for more examples.
* See [Get Factors of Numbers in Kotlin
](

[To see links please register here]

) which shows another example of a Python comprehension versus Kotlin.
* See [Kotlin Extensions Functions for Collections](

[To see links please register here]

) in the API reference guide.
Reply

#3
val newls = (1..100).filter({it % 7 == 0})

in Kotlin is equivalent to the following Python code

newls = [i for i in 0..100 if i % 7 ==0]
Reply

#4
Just for exercise the closest to python will be:
```
infix fun <I, O> ((I) -> O).`in`(range: Iterable<I>): List<O> = range.map(this).toList()
infix fun <I> Iterable<I>.`if`(cond: (I) -> Boolean): List<I> = this.filter(cond)

fun main() {
{ it: Int -> it + 1 } `in` 1..2 `if` {it > 0}
}
```
Reply

#5
**Map comprehension**

```
import kotlin.math.sqrt

val numbers = "1,2,3,4".split(",")

val roots = numbers.associate { n -> n.toInt() to sqrt(n.toFloat()) }

println(roots) // prints {1=1.0, 2=1.4142135, 3=1.7320508, 4=2.0}
```
If keys are untransformed elements of source list, even simpler:
```
val roots = numbers.associateWith { n -> sqrt(n.toFloat()) }
```
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through