Reputation: 161
i'm playing a little bit with Kotlin and i don't understand this so, maybe someone can explain it to me.
I have a data class which is:
data class Person (var name : String, var age : Int)
And i want to create a List which contains the Person with the multiplied age multiplied per 2, only on even items. So i created a new List and create a mutableList from it because i want to change their age. I did it in the following way:
val personA = Person("john", 25)
val personB = Person("Ane", 10)
val personC = Person("will", 20)
val personList = listOf(personA, personB, personC)
var mutablePersons = mutableListOf<Person>()
mutablePersons.addAll(personList)
And now i'm trying to create a new list with the items from mutablePersons modified. So i already did the following:
val mutablePersonsAgeChanged = mutablePersons.mapIndexed { index, person ->
if (index.rem(2) == 0) {
person.age = person.age * 2
}
}
And.. there is something i'm not doing well, because mutablePersonAgeChanged is List<Any>
and i want a List<Person>
.
So, my question is. What im doing wrong? How can make this mapIndexed Returns List<Person>
Upvotes: 9
Views: 25467
Reputation: 16905
The mapIndexed will pass each item, and its index into the Lambda. It then adds the result of the Lambda to the new list. In your case, the return value of the Lambda is the if
(as most items are expressions in Kotlin).
The result of the if
is either Unit in the case of index % 2 == 0 because the setter for age returns a Unit.
If the if
is false, it will also return Unit.
To fix it, you need to return person
at the end of the map.
So if you made your code as below, it will work.
val mutablePersonsAgeChanged = mutablePersons.mapIndexed { index, person ->
if (index.rem(2) == 0) {
person.age = person.age * 2
}
person
}
It's also not necessary to create a List, and then add all the elements to a mutableList. Just change listOf(personA, personB, personC)
to mutableListOf(personA, personB, personC)
Upvotes: 4
Reputation: 4184
In your case the function passed as the parameter of mapIndexed
was inferred to Any
because you miss the else
branch of your if
statement. Also, I'd like to mention that mapIndexed
is like map
but with the index
of the element, so you need to pass a function that transforms every element.
Example
data class Person (val name : String, val age : Int)
val personList = listOf(
Person("John", 25),
Person("Ane", 10),
Person("will", 20)
)
val personListAgeChanged = personList.mapIndexed { index, person ->
if (index.rem(2) == 0) person.copy(age = person.age*2)
else person
}
println(personListAgeChanged)
Output
[Person(name=john, age=50), Person(name=Ane, age=10), Person(name=will, age=40)]
In this case, you pass a function that doubles the age of each person in the list, please notice that never any variable or list is mutated, which should be the prefered approach.
Upvotes: 17