https://kotlinlang.org logo
#stdlib
Title
# stdlib
s

spand

02/12/2020, 8:59 AM
Are there any generalized functions like joinToString ? Currently I just need something like a forEach but with a sideeffect between elements.
g

gian

02/12/2020, 9:26 AM
Something like this?
Copy code
.zipWithNext().forEach { (a, b) -> }
s

spand

02/12/2020, 9:34 AM
I cant quite get that to work ie.
Copy code
listOf(1,2,3).zipWithNext().forEach {  println(it.first); println("-"); println(it.second) }
Gives
Copy code
1-22-3
w

wasyl

02/12/2020, 10:06 AM
There’s also
Iterable<T>.joinTo
where you can provide an appendable buffer to put elements into
c

Czar

02/12/2020, 12:48 PM
@spand, I'm a bit confused, what did you want to get instead of
Copy code
1-2
2-3
?
s

spand

02/12/2020, 12:48 PM
1-2-3
c

Czar

02/12/2020, 12:49 PM
Oh, I see, then @wasyl’s answer is correct
s

spand

02/12/2020, 12:51 PM
Not really. His answer does not take the question into context
I ended up making my own:
Copy code
private inline fun <T> Iterable<T>.intersperseEach(separator: () -> Unit = {}, before: () -> Unit = {}, after: () -> Unit = {}, action: (T) -> Unit): Unit {
    val ite = iterator()
    var first = true
    before()
    while (ite.hasNext()) {
        if (first) {
            first = false
        } else {
            separator()
        }
        action(ite.next())
    }
    after()
}
Seems like it fits in the stdlib imo.
c

Czar

02/12/2020, 12:52 PM
Oh, I see, I'm a bit slow today it seems, sorry 🙂
s

spand

02/12/2020, 12:53 PM
I just wanted to ask if there was another function in the stdlib that was close enough.
w

wasyl

02/12/2020, 12:54 PM
Yeah I just mentioned another method somewhat relevant to joining. But I’m curious what’s the use case for the method above? It just performs some side effects during iteration, right?
s

spand

02/12/2020, 12:57 PM
The current case is printing line separators between elements in kotlinx.html ie.:
Copy code
<div></div>
<hr />
<div></div>
Pretty standard stuff
k

Kristoffer Andersen

02/12/2020, 12:57 PM
Maybe flatten it a little? I am just golfing, now 🙂
Copy code
val ite = iterator()
    before()
    if (!ite.hasNext()) { after(); return }
    action(ite.next())
    while (ite.hasNext()) {
        separator()
        action(ite.next())
    }
    after()
👍 1
s

spand

02/12/2020, 12:57 PM
And since I am not working with strings joinToString is no good
c

Czar

02/12/2020, 1:02 PM
Copy code
val result = mutableListOf<String>()

val input = listOf(1, 2, 3)

val iter = input.iterator()
iter.forEachRemaining {
	result.add(it.toString())
	if (iter.hasNext()) result.add("-")
}
println(result) // gives: [1, -, 2, -, 3]
Isn't this what you're looking for then?
👍 1
s

spand

02/12/2020, 1:05 PM
Yes that would work
c

Czar

02/12/2020, 1:07 PM
Copy code
fun <T> Iterable<T>.intersperseEach(
   separator: () -> Unit = {},
   before: () -> Unit = {},
   after: () -> Unit = {},
   action: (T) -> Unit
) {
   before()
   val iterator = iterator()
   iterator.forEachRemaining {
      action(it)
      if (iterator.hasNext()) separator()
   }
   after()
}

listOf("<div></div>", "<div></div>").intersperseEach(
	separator = { println("<br />") },
	action = ::println
)
// prints:
// <div></div>
// <br />
// <div></div>
s

spand

02/12/2020, 1:16 PM
https://youtrack.jetbrains.com/issue/KT-36647 if anyone wants to watch 😉
c

Czar

02/12/2020, 1:17 PM
@spand I'm
@Alexander_Czar
on YT
👍 1
thanks for the attribution 🙂
s

spand

02/12/2020, 1:34 PM
Credit where credit is due
d

Derek Peirce

02/13/2020, 4:10 AM
Is there a point to
before
and
after
? Those could each be replaced with
also
.
s

spand

02/13/2020, 8:19 AM
Good point