https://kotlinlang.org logo
#announcements
Title
# announcements
m

mending3

02/24/2021, 4:50 AM
got-stuck let's say I have this code:
Copy code
val string = "<p></p>this<p></p>"
        
val arrs = listOf("<p data-id=\"1\"></p>", "<p data-id=\"2\"></p>")

var replacedString = ""

arrs.forEach {
    val pTag = "<p></p>"

    replacedString = string.replace(pTag, it)

}

println(replacedString)
It should show
<p data-id="1"></p>this<p data-id="2"></p>
, but it shows
<p data-id="2"></p>this<p data-id="2"></p>
instead
n

nanodeath

02/24/2021, 4:51 AM
that's likely going to require an HTML parser
also you have an attribute on a closing tag in your example
m

mending3

02/24/2021, 4:53 AM
yea. I've considered it
I've edited my post. got typo
but I got stuck on the logic
n

nanodeath

02/24/2021, 4:56 AM
you could just do
"<p data-id=\"${arrs.first()}\"></p>this<p data-id=\"${arrs.last()}\"></p>"
m

mending3

02/24/2021, 5:00 AM
the problem is the transformed string and the
listOf
would be dynamic so if I have:
Copy code
val arrs = listOf("1", "2", "3")
the transformed string would look:
<p data-id="1"></p>this<p data-id="2"></p><p data-id="3"></p>
or
<p data-id="1"></p>this<p data-id="2"></p>that<p data-id="3"></p>
so on and so forth
n

nanodeath

02/24/2021, 5:01 AM
so...really it's just interleaving two things, yeah?
m

mending3

02/24/2021, 5:02 AM
yes
Copy code
var replacedString = ""

        arrs.forEach {
            val pTag = "<p></p>"

            replacedString = string.replace(pTag, it)

        }
        
        println(replacedString)
this doesn't work it always gets the last index so the
data-id
value is
3
n

nanodeath

02/24/2021, 5:10 AM
maybe you can do something like this.
zip
only produces a collection as long as the shorter one though.
m

mending3

02/24/2021, 5:13 AM
why is there
letters
variable?
n

nanodeath

02/24/2021, 5:15 AM
you have a list of ids and a list of whatever "this" and "that" is
m

mending3

02/24/2021, 6:00 AM
what is the reason of having
letters
variable?
because I see that code gets out of context of my problem thank you anyway
I've edited my post to get the better picture out of it
p

Petter Måhlén

02/24/2021, 7:08 AM
the issue is
replacedString = string.replace(…)
. you’re overwriting the
replacedString
var on each iteration, and reading from the original
string
☝🏻 1
d

Dave K

02/24/2021, 7:19 AM
It looks like you want to replace the <p></p> from the original string with whatever the arrs are and then if there are extra arrs you want to just append them to the end. How about
Copy code
val values = string.split(pTag)
arrs.zip(values + List(arrs.length - values.length) { “” }) { a,b -> listOf(a,b) }.flatten().joinToString(“”)
So essentially remove all the ptags and produce a list of this (and that), and then pad that list with empty strings so that it’s the same length as the list of arrs. Then zip the two lists together finally joining them all into a single string.
In the case your arrs is just 1, 2, 3 you could add a map before the zip.
arrs.map { “<p data-id=\”$it\”></p>” }.zip...
Allowing you to create your p tag with data id from the number values before zipping them in place
If your list of arrs might be shorter than the list of your strings then you’d need to add additional logic of course. But yeah, replace won’t work because replace will replace all instances of the pTag, and the replacedString will be overwritten every time until the final time resulting in just the last arr showing up
p

Petter Måhlén

02/24/2021, 7:28 AM
i guess in my opinion, this solution in itself is not usually a good idea. either pick an existing templating engine or hard-code your cases instead of using two separate things (the string and the array) that you need to manually keep in synch. this is unlikely to be a safe solution that is easy to maintain going forward. without more context on how you’re going to use it, it’s hard to give good advice about what would be a good alternate solution.
👆 2
d

Dave K

02/24/2021, 7:32 AM
Absolutely. Depends what the use case is as to what the best solution is. But from the perspective of wanting to replace some string with an element from some list one by one and then tuck the remaining elements of the list at the end I think it’s a viable approach. Whether it’s good for the intended use depends.
n

nkiesel

02/24/2021, 7:29 PM
Many useful insights here. But just to provide the answer to the initial question: your code does not work because 1. you modify
string
instead of
replacedString
in your loop iterations. Thus, every iteration starts with the same data and overwrites whatever the previous iteration did 2.
String::replace
replaces all matches in the String and not just the first one. Thus, your 2nd (and final) iteration does
replacedString = "<p></p>this<p></p>".replace("<p></p>", "<p data-id=\"2\"></p>")
and you end up with the result you see. Minimal changes to your code to provide the desired output:
Copy code
var replacedString = string

arrs.forEach {
   	val pTag = "<p></p>"
   	replacedString = replacedString.replaceFirst(pTag, it)
}
1
m

Matteo Mirk

02/25/2021, 11:00 AM
5 Views