Hey I have object of `Event`. I want to combine al...
# codingconventions
v
Hey I have object of
Event
. I want to combine all property value into single string. I did this without any problem. I want to know is there any better way to optimise this code in memory, efficiency etc. SingleEventString.kt
Copy code
fun main() {
        var newString: String? = null
        val eventList = createData()
        eventList.forEachIndexed { index, event ->
            val title = event.title
            val status = event.status
            if (!title.isNullOrEmpty()) {
                newString = if(index == 0){
                    "$title"
                }else{
                    "$newString $title"
                }
            }
            if (!status.isNullOrEmpty()) {
                newString = "$newString $status"
            }
        }
        println(newString)
    }
    
    data class Event(val title: String? = null, val status: String? = null)
    
    fun createData() = listOf(
        Event("text 1", "abc"),
        Event("text 2", "abc"),
        Event("text 3", "abc"),
        Event("text 4", "abc"),
        Event("", "abc"),
        Event(null, "abc")
)
s
You could use a StringBuilder for this (either on its own or via buildString)
l
To add to that, you could use
eventList.fold(StringBuilder()) { builder, event -> ... }.toString()
v
what is builder and event?
l
builder would be the StringBuilder, and event would be each event one after the other. But I am just realizing that what you want is even simpler:
eventList.joinToString(separator = " ") { event -> ... }
. This maps each event to a string and concats them with a space separator
👌 3
v
That's great. I'll try on my side
@Luke I tried this code
Copy code
fun main() {
    var newString: String? = null
    val eventList = createData()
    eventList.joinToString(separator = " ") { event ->
        val title = event.title
        val status = event.status
        if (!title.isNullOrEmpty()) {
            newString = "$newString $title"
        }
        if (!status.isNullOrEmpty()) {
            newString = "$newString $status"
        }
        newString.toString()
    }
    println(newString)
}
and getting this
null text 1 abc text 2 abc text 3 abc text 4 abc abc abc
How to remove null in this ?
l
Copy code
val newString = eventList.joinToString(separator = " ") { event ->
    when {
        title.isNullOrEmpty() -> status.orEmpty()
        status.isNullOrEmpty() -> title
        else -> "$title $status"
    }
}
v
Sorry can you please explain me what is going on this 1.
Copy code
event.title.isNullOrEmpty() ->  event.status.orEmpty()
2.
Copy code
event.status.isNullOrEmpty() -> event.title
why 1st one have
orEmpty()
and 2nd don't ?
@Luke 👆
l
1. If the title is null or is the empty string, you return the status. If the status is null, you return the empty string 2. Since we already checked that the title is neither null or empty, then calling orEmpty here is redundant
Another solution, which you might find easier to understand (?), is this:
Copy code
val newString = createData().asSequence()
    .flatMap { sequenceOf(it.title, it.status) }
    .filterNotNull()
    .filterNot { it.isEmpty() }
    .joinToString(separator = " ")
🙌 2
Basically, create an iteration of every title and status, filter out nulls and empty strings, and concatenate with space separator
v
Ok now this is great example. I can easily understand that one. Thanks a million
And above solution is working fine
n
you cold also replace
.filterNotNull().filterNot { it.isEmpty() }
with
.filterNot { it.isNullorEmpty() }
âž• 1
v
Sure thanks
e
Copy code
createData().flatMap {
    listOfNotNull(
        it.title?.ifEmpty { null },
        it.status?.ifEmpty { null },
    }
}.joinToString(separator = " ")
v
@ephemient thank you so much. Can you please explain me what is difference between
flatMap
and
Map
? Thanks
e
.flatMap { … }
behaves like
.map { … }.flatten()
n
listOfNotNull returns a list (containing 0, 1, or 2 elements in your concrete example) for every item returned from createData. Therefore, a .map would return a list of these lists. flatMap (as just explained) flattens this to a simple list by concatenating all the inner lists.
Copy code
listOf(Data("t1", null), Data(null, "s2"), Data("t3", "s3")).map { listOfNotNull( it.title?.ifEmpty { null }, it.status?.ifEmpty { null }) } // [[t1], [s2], [t3, s3]]
listOf(Data("t1", null), Data(null, "s2"), Data("t3", "s3")).flatMap { listOfNotNull( it.title?.ifEmpty { null }, it.status?.ifEmpty { null }) } // [t1, s2, t3, s3]
v
great explanation. Thank you so much guys. @nkiesel @ephemient