16

I am working with this code.

fun main(args : Array<String>){

    val someArray : Array<Int> =  arrayOf(3,53,2,521,51,23,512,34,124);

    println("Original array is ")

    someArray.forEach {print("$it , ")}

    someArray.map({num -> num*2})

    println("Changed array is ")

    println()

    someArray.forEach { print("$it , ") }
}

But the map function does not seem to work. Here is what it prints

Original array is 3 , 53 , 2 , 521 , 51 , 23 , 512 , 34 , 124 , Changed array is

3 , 53 , 2 , 521 , 51 , 23 , 512 , 34 , 124 ,

My question is why is the array not doubling the value of its elements? What i am i missing here?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Dishonered
  • 8,449
  • 9
  • 37
  • 50

4 Answers4

14

You could always define your own extension that does what you need:

fun <T> Array<T>.mapInPlace(transform: (T) -> T) {
    for (i in this.indices) {
        this[i] = transform(this[i])
    }
}

Usage would look like this:

someArray.mapInPlace { num -> num * 2 }

Note that there are special non-generic classes for primitive arrays, such as IntArray (see also this question), so you should probably be using those instead of the generic one. Of course then you'd have to define this extension for each of them separately, like:

fun IntArray.mapInPlace(transform: (Int) -> Int) { ... }
fun DoubleArray.mapInPlace(transform: (Double) -> Double) { ... }
zsmb13
  • 85,752
  • 11
  • 221
  • 226
10

From the documentation, map doesn't modify the items in place but rather returns a List containing the result of the mapping function applied to all the items:

Returns a list containing the results of applying the given transform function to each element in the original array [or collection or map, depending on the receiver].

So, to get the expected result you should do something like:

val doubled = someArray.map { n -> n * 2}
doubled.forEach { print("$it , ") }

EDIT

From what I know there's no built-in function allowing you to map items in-place. However, in your case you're dealing with an Array, which is a mutable data structure, so the alternative is to use an old-style loop to iteratively transform its items (you can apply the same logic with MutableList or other mutable data structures using an Iterator to update values). Something like this:

fun main(args: Array<String>) {
    val someArray: Array<Int> = arrayOf(3, 53, 2, 521, 51, 23, 512, 34, 124);

    someArray.forEach { print("$it , ") }

    println()

    for (i in 0 until someArray.size) {
        someArray[i] = someArray[i] * 2
    }

    someArray.forEach { print("$it , ") }
}
user2340612
  • 10,053
  • 4
  • 41
  • 66
6

An alternative is to use forEachIndexed instead of map. Replace

someArray.map({num -> num*2})    

by

someArray.forEachIndexed{ index, num -> someArray[index] = num * 2 }    
David Varela
  • 101
  • 1
  • 4
2

As many have stated, the map returns a new list and doesn't modify the original.

The most efficient way to rewrite your intended code is to do

// assuming you want to act upon individual elements in the list
fun main(args : Array<String>) {
    val someArray : Array<Int> =  arrayOf(3,53,2,521,51,23,512,34,124);
    println("Original array is $someArray")
    someArray
        .map { it * 2 }
        .forEach { print("$it , ") }
}

or if you just want to see the comma separated list of values

// really just want to print the transformed values instead
fun main(args : Array<String>) {
    val someArray : Array<Int> =  arrayOf(3,53,2,521,51,23,512,34,124);
    println("Original array is $someArray")
    someArray
        .map { it * 2 }
        .also { print(it.joinToString()) }
}
Ryba
  • 1,249
  • 10
  • 17