Is there a better (more functional way) to write t...
# codereview
c
Is there a better (more functional way) to write this?
Copy code
people.addAll(
    getAllPeople().map { Pair(it.first.orEmpty(), it.last.orEmpty()) }
)
I basically have a variable called people which is a Pair<>, and then I have the return of getAllPeople which is a Person.
p
getAllPeople()
only ever returns a 2 element list?
โ“ 1
or
getAllPeople()
returns
List<Pair<String, String>>
and you want
people
to be a
List<Person>
?
no, the opposite of this?
the obvious thing to do is to initialize
people
entirely in the
map
call:
Copy code
val people = getAllPeople().map { it.first to it.last }
๐Ÿ‘ 1
c
sorry, first and last are firstName and lastName. So I'm mapping all of the people that come from getAllPeople into Pairs.
p
that's about how I'd do it, under the assumption it doesn't make sense for your purposes to have someone with an empty first or last name (which may or may not be true)
j
I basically have a variable called people which is a Pair<>, and then I have the return of getAllPeople which is a Person.
You mean lists of those things, right?
p
on a meta-level, I'm kinda curious why you're after this - I find Pair less ergonomic to use, and if you've already got a named class with useful members it's probably easier to hand that around
โž• 4
w
I would write something like this:
Copy code
data class People(val firstName: String?, val lastName: String?)
fun getAllPeople(): List<People> = emptyList()
fun asas() {
    val people = mutableListOf<Pair<String, String>>()
//    people.addAll(
//        getAllPeople().map { Pair(it.firstName.orEmpty(), it.lastName.orEmpty()) }
//    )
    getAllPeople()
        .map { it.firstName.orEmpty() to it.lastName.orEmpty() }
        .let(people::addAll)
}
For me the reason would be to read first what is happening first, so basically
getAllPeople
, then
map
, the
people.ddAll
. But I would try to avoid the mutable list anyway, which would make it nicer to read from the begin. Anyway, my only suggestion here would be if you could potentially avoid mutability and perhaps can use immutable data there? Also what @Paul Griffith said above.
k
When dealing with Pair(firstName, lastName), I wouldn't use the
to
infix function to create the pair. The word "to" implies a key-value relationship. First name does not map to surname; it's just a pair of names. Therefore I would use Pair(firstName, lastName) even though it's slightly longer. It's more readable.
๐Ÿ‘Œ 1
โž• 1
r
getAllPeople().mapTo(people){...}
๐Ÿ‘ 1
โž• 1
c
I really like mapTo!! Thanks that's pretty much what my question was really asking. How can I map one list of A to a list of B.
j
But most of the time you should use read-only lists instead of a mutable list. So
val mappedList = sourceList.map { ... }
is preferable over creating a mutable list first and then using
mapTo
โž• 2
I'm still quite curious (like @Paul Griffith ) as to why you want to map those objects to the lesser
Pair
. It would seem better to make the properties of
Person
non nullable in the first place, or to create an equivalent data class with non-nullable fields if you really need the current
Person
class
p
yeah, the 'more functional' way to do things is to not have side effects - the transformation of A to B should be the function, and
map
should be used to apply it.
mapTo
is useful if, say, you have a collection with some elements already (that you can't fit into your starting collection) or something like that, but in the problem described, you don't need (and should avoid) creating the list and then populating it in two steps
๐Ÿ‘ 1
c
Interesting. My example I gave isn't what I'm actually using in real life, it's just as simple of an example as I could come up with. But for example, some real life examples is that I have a call to getAllMovies() and that gives me back a list of MovieDTO. Now I want to map my MovieDTOs into MovieUI objects. So I'm just looking for how to map between two very similar classes, but are different classes.
j
Ok that answers the
Pair
stuff then. The
mapTo
vs
map
still holds, though. In the case you mention, you should use
map
.
c
Okay. So if my map just transforms from ObjectA to ObjectB, then the output will just be a List<ObjectB> and then I can addAll to my variable of listOfObjectB?
j
Sorry if I was unclear. If your goal really is to add to a mutable list, then of course
mapTo
is what should be used instead to avoid an extra list. But our point was that if you don't already have a mutable list, you should probably not create a mutable list at all and just use the result of map directly