Table of contents
In this article , lets discuss about Kotlin Collections operation - transformation functions
Kotlin Transformation function builds a new collection based on the transformation rules passed in the function.
Map
- Mapping transformation creates a collection from the result of function on the another collection's element
map()
applies the given function to each element and returns the list of lambda result
order of elements is same as order of original elements collection's order
val numbers = setOf(1, 3, 2, 5, 4, 6, 7, 9, 0)
// map
println(numbers.map { it * 3 })
//output ; [3, 9, 6, 15, 12, 18, 21, 27, 0]
mapIndexed()
- Apply a
map()
transformation that additionally uses the element index as argument
val numbers = setOf(1, 3, 2, 5, 4, 6, 7, 9, 0)
//map indexed
println(numbers.mapIndexed { index: Int, i: Int -> "index:$index - value:$i" })
// output : [index:0 - value:1, index:1 - value:3, index:2 - value:2, index:3 - value:5,
// index:4 - value:4, index:5 - value:6, index:6 - value:7, index:7 - value:9,
// index:8 - value:0]
mapNotNull() & mapNotNullIndexed()
- If the transformation produces null on certain element , we can filter out null from result collection
val numbers = setOf(1, 3, 2, 5, 4, 6, 7, 9, 0)
//map null
println(numbers.mapNotNull { if (it == 5) null else it * 10 })
// output : [10, 30, 20, 40, 60, 70, 90, 0]
//map indexed null
println(numbers.mapIndexedNotNull { index, i -> if (index == 4) null else i * 10 })
// output : [10, 30, 20, 50, 60, 70, 90, 0]
When transforming maps , there are two options
mapKeys()
-> transform key leaving values unchangedmapValues()
-> transform values leaving keys unchanged
val numbersMap = mapOf("Key1" to 1, "Key2" to 2,
"Key3" to 3, "Key4" to 4, "Key5" to 5)
//map keys and map values
println(numbersMap.mapKeys { it.key.reversed() })
// output : {1yeK=1, 2yeK=2, 3yeK=3, 4yeK=4, 5yeK=5}
println(numbersMap.mapValues { "${it.value} + ${it.key.uppercase()}" })
// output : {Key1=1 + KEY1, Key2=2 + KEY2, Key3=3 + KEY3,
// Key4=4 + KEY4, Key5=5 + KEY5}
Zip
Zipping transformation is building pairs from elements with same positions in two collections
zip()
returns the list of pair object
if the collection have different sizes , then the result of
zip()
is smaller size collection size and the result will not contain the larger collection's last element
val studentName = listOf("stu 1", "stu 2", "stu 3", "stu 4")
val studentAge = listOf(20, 35, 5, 0, 30)
// zip
println(studentName zip studentAge)
// output : [(stu 1, 20), (stu 2, 35), (stu 3, 5), (stu 4, 0)]
Zip with transformation function takes 2 parameters
1.Receiver element
2.Argument element
Transformation function called on pairs of receiver and argument element with same position
val studentName = listOf("stu 1", "stu 2", "stu 3", "stu 4")
val studentAge = listOf(20, 35, 5, 0, 30)
//zip transformation
println(studentName.zip(studentAge) { name, age ->
"The Student name is $name amd the age is $age"
})
// output : [The Student name is stu 1 amd the age is 20,
//The Student name is stu 2 amd the age is 35,
// The Student name is stu 3 amd the age is 5,
//The Student name is stu 4 amd the age is 0]
unzip()
We can do the reverse transformation on the list of pairs and the result is of two lists
1.First list contains first element of each pair
2.Second list contains second element
// unzipping
val studentInfo = listOf(
"stu1" to 20,
"stu2" to 35,
"stu3" to 5,
"st4" to 0
)
println(studentInfo.unzip())
// output : ([stu1, stu2, stu3, st4], [20, 35, 5, 0])
Associate
- Allow building maps from collection elements and values associated from them
associateWith()
- creates a map in which element of original collection are keys and values are result of given transformation function
val numbers = listOf(1, 3, 5, 3, 7)
// associateWith
println(numbers.associateWith { it * 2 + 1 })
// output : {1=2, 3=6, 5=10, 7=14}
associateBy()
creates a map with original collection as values
it takes a function that returns the key based on elements transformation function
val numbers = listOf(1, 3, 5, 3, 7)
// associateBy
println(numbers.associateBy { it * 2 })
//output :{2=1, 6=3, 10=5, 14=7}
associate()
For building maps where both keys and values are produced from the original collection elements
It takes a lambda function and returns a
Pair
: key and value of corresponding map entry
associate()
produces short living pair objects which may affect performance val numbers = listOf(1, 3, 5, 3, 7)
// associate
println(numbers.associate {
it to (it * 2 + 3)
}
)
//output : {1=5, 3=9, 5=13, 7=17}
Flatten
- operates on nested collection that provide flat access to nested collection elements
flatten()
call it on the collection of elements (list of sets)
returns the list of elements in the nested collection
val sampleSetList = listOf(
setOf(3, 4, 5),
setOf(0, 1, 2),
setOf(7, 8, 9),
setOf(6, 7, 8)
)
// flatten
println(sampleSetList.flatten())
//output : [3, 4, 5, 0, 1, 2, 7, 8, 9, 6, 7, 8]
flatMap()
flexible way to process nested collection
takes a function that maps a collection element to another collection
returns a single list on its return values on all elements
so basically
flatMap()
is a mixture of bothmap()
andflatten()
val containers = listOf(
listOf("one", "two", "three"),
listOf("four", "five", "six"),
listOf("seven", "eight")
)
// flatmap
println(containers.flatMap {
it.asReversed()
})
// output : [three, two, one, six, five, four, eight, seven]
String Representation
- If we need collection in a readable format , use the transform function like
joinTostring(
) andjoinTo()
joinToString()
- builds a string string from the collection result based on provided argument
val numbers = listOf("one", 1, "two", 2, "three", 3)
// joinToString
println(numbers.joinToString())
// output : one, 1, two, 2, three, 3
joinTo()
builds a string from collection but appends the result to the given append able object
result is a string of collection elements separated by commas with spaces
val numbers = listOf("one", 1, "two", 2, "three", 3)
// joinTo
val listContents = StringBuffer("The contents are -> ")
numbers.joinTo(listContents)
println(listContents)
//output :The contents are -> one, 1, two, 2, three, 3
joinToString() - prefix, postfix and separator
- To build a custom string representation , we can user the prefix, postfix and separator in the j
oinToString()
val numbers = listOf("one", 1, "two", 2, "three", 3)
// joinToString
println(
numbers.joinToString(
separator = " -- ",
prefix = "Begin: ",
postfix = " :End"
)
)
//output: Begin: one -- 1 -- two -- 2 -- three -- 3 :End
joinToString() - limit and truncate
This limit and truncate parameter is used in
joinToString()
for bigger collections , this will limit the elements in resultif the limit is reached , truncated argument will replace the rest of all elements in the collection
// limit and truncate
val numbersList = (1..100).toList()
println(
numbersList.joinToString(
limit = 12, truncated = " and so on"
)
)
//output ; 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, and so on
joinToString() -
transform
- To customize the elements in collections , we can use transform function as follows
// transform
val numbersString = listOf("one", "two", "three")
println(numbersString.joinToString {
"Element -> ${it.reversed().uppercase()}"
}
)
//output: Element -> ENO, Element -> OWT, Element -> EERHT
Please leave your comments to improve.
Happy and Enjoy coding