Reputation: 1109
I have a list of Longs in Kotlin and I want to make them strings for UI purposes with maybe some prefix or altered in some way. For example, adding "$" in the front or the word "dollars" at the end.
I know I can simply iterate over them all like:
val myNewStrings = ArrayList<String>()
longValues.forEach { myNewStrings.add("$it dollars") }
I guess I'm just getting nitpicky, but I feel like there is a way to inline this or change the original long list without creating a new string list?
EDIT/UPDATE: Sorry for the initial confusion of my terms. I meant writing the code in one line and not inlining a function. I knew it was possible, but couldn't remember kotlin's map
function feature at the time of writing. Thank you all for the useful information though. I learned a lot, thanks.
Upvotes: 0
Views: 1729
Reputation: 19622
Like people have said, unless there's a performance issue here (like a billion strings where you're only using a handful) just creating the list you want is probably the way to go. You have a few options though!
Sequences are lazily evaluated, when there's a long chain of operations they complete the chain on each item in turn, instead of creating an intermediate full list for every operation in the chain. So that can mean less memory use, and more efficiency if you only need certain items, or you want to stop early. They have overhead though so you need to be sure it's worth it, and for your use-case (turning a list into another list) there are no intermediate lists to avoid, and I'm guessing you're using the whole thing. Probably better to just make the String
list, once, and then use it?
Your other option is to make a function that takes a Long
and makes a String
- whatever function you're passing to map
, basically, except use it when you need it. If you have a very large number of Longs
and you really don't want every possible String
version in memory, just generate them whenever you display them. You could make it an extension function or property if you like, so you can just go
fun Long.display() = "$this dollars"
val Long.dollaridoos: String get() = "$this.dollars"
print(number.display())
print(number.dollaridoos)
or make a wrapper object holding your list and giving access to a stringified version of the values. Whatever's your jam
Also the map
approach is more efficient than creating an ArrayList
and adding to it, because it can allocate a list with the correct capacity from the get-go - arbitrarily adding to an unsized list will keep growing it when it gets too big, then it has to copy to another (larger) array... until that one fills up, then it happens again...
Upvotes: 2
Reputation: 23147
In Kotlin inline
is a keyword that refers to the compiler substituting a function call with the contents of the function directly. I don't think that's what you're asking about here. Maybe you meant you want to write the code on one line.
You might want to read over the Collections documentation, specifically the Mapping section.
The mapping transformation creates a collection from the results of a function on the elements of another collection. The basic mapping function is
map()
. It applies the given lambda function to each subsequent element and returns the list of the lambda results. The order of results is the same as the original order of elements.val numbers = setOf(1, 2, 3) println(numbers.map { it * 3 })
For your example, this would look as the others said:
val myNewStrings = longValues.map { "$it dollars" }
I feel like there is a way to inline this or change the original long list without creating a new string list?
No. You have Long
s, and you want String
s. The only way is to create new String
s. You could avoid creating a new List
by changing the type of the original list from List<Long>
to List<Any>
and editing it in place, but that would be overkill and make the code overly complex, harder to follow, and more error-prone.
Upvotes: 2
Reputation: 28066
You can use the map
-function on List
. It creates a new list where every element has been applied a function.
Like this:
val myNewStrings = longValues.map { "$it dollars" }
Upvotes: 2
Reputation: 10537
You are looking for a map, a map takes a lambda, and creates a list based on the result of the lambda
val myNewStrings = longValues.map { "$it dollars" }
map
is an extension that has 2 generic types, the first is for knowing what type is iterating and the second what type is going to return. The lambda we pass as argument is actually transform: (T) -> R
so you can see it has to be a function that receives a T
which is the source type and then returns an R
which is the lambda result. Lambdas doesn't need to specify return because the last line is the return by default.
Upvotes: 2