Remove character or word from string in kotlin - kotlin

Hey I want to remove character/word or sentence from string.
For example
val string = "Hey 123"
or
val string = "Hey How are you 123"
or
val string = "Hey!! How are you 123"
and output
string = 123

If you only want the digits:
val result = string.filter { it.isDigit() }
Alternatively if you want to omit letters (and maybe also whitespace):
val result = string.filter { !it.isLetter() }
val result = string.filter { !it.isLetter() && !it.isWhitespace() }

Related

Kotlin Data Class Parsing Mutiple member properties at once

Let say I have a data class called Class A
data class ClassA {
val x0 = ""
val x1 = "some string"
val x2 = "some string"
val x3 = "some string"
val x4 = "some string"
val x5 = ""
val x6 = ""
val y = ""
val z = ""
}
I can retrieve the value of these class member thru its class object
val obj = ClassA()
// if the properties has prefix x and not empty then concatenate to this x variable
val x = obj.x1 + obj.x2 + etc...
...
Let say if this data class has 50+ x(n) in it and I want to retrieve any member that does not have an "empty string or null" and match the prefix then how do I do it dynamically (can be a for-loop), instead of type out statically every single properties that I want to retrieve, is there an alternative way to do it?
You could solve that with Reflection:
data class ClassA (
val x0: String = "",
val x1: String = "some string 1",
val x2: String = "some string 2",
val x3: String = "some string 3",
val x4: String = "some string 4",
val x5: String = "",
val x6: String = "",
val y: String = "",
val z: String = ""
)
val obj = ClassA()
val result = ClassA::class.java.declaredFields // or:
.filter { it.name.startsWith("x") }
.onEach { it.isAccessible = true }
.map { it.get(obj) }
.joinToString("; ")
println(result)
This will print:
; some string 1; some string 2; some string 3; some string 4; ;
If you want to omit x0, x5, and x6, which all are empty strings, and you want to concatenate without semicolon:
val result = Class::class.java.declaredFields
.filter { it.name.startsWith("x") }
.onEach { it.isAccessible = true }
.map { it.get(obj) }
.filter { it != "" }
.joinToString("")
I'm going to answer you question and provide a way of doing it, however, I highly recommend against doing it this way simply because while it works, it is seen as hacky and you'd be better off solving this by changing the multiple fields/properties into a collection of some sort instead.
You can use reflection to do it without having to type out all of the values manually.
To do it via reflection, you will have to do something like this.
fun getNonEmptyStrings(input: A): List<String> {
val members = A::class.memberProperties
return members
.filter { it.name.startsWith("x") }
.map { it.get(input) }
.filterIsInstance<String>()
.filter { it.isNotBlank() }
}
There might be some other form of meta-programming that is better suited to this, but I'm not sure what that would be.

Delete all letters from String

How can i delete all letters from String?
I've got given String:
val stringData ="ABC123.456"
Output value:
val stringData ="123.456"
We can try regex replacement here:
val regex = """[A-Za-z]+""".toRegex()
val stringData = "ABC123.456"
val output = regex.replace(stringData, "")
println(output) // 123.456

Kotlin: Find the first line of a file that matches a regex, and return captured values

i want get text from a file by using regEx and want save the file with a new name (using the results of the regEx-Find).
My Problem is that i cant get/return the correct genearated (in this example xyz maur) out of the function readFileLineByLineUsingForEachLine(fileName: String) the new newFileName which was generated (sucessfully as expected) in the function.
Line 1 of Source:
start {"Name":"xyz","Civ":"maur","Team":0}
My Prototype:
fun main() {
val f = "./commands.txt";
var newFileName = readFileLineByLineUsingForEachLine(f)
print(newFileName.)
val source = Paths.get(f)
val target = Paths.get("/home/x/snap/0ad/199/.local/share/0ad/replays/0.0.24/2021-03-14_0016/" + newFileName)
// try {
// val move = Files.move(
// source,
// target
// )
// } catch (e: IOException) {
// e.printStackTrace()
// }
};
fun readFileLineByLineUsingForEachLine(fileName: String) // https://www.baeldung.com/kotlin/read-file
= File(fileName).forEachLine lit#{
// "Name":"Cleisthenes"
val regexString = """
"Name":(?<Name>"\w+").*?"Civ":(?<Civ>"\w+").*?"Team":0
""".trim()
var regex = Regex(regexString)
var matched = regex.find(it)?.groupValues
val Name = matched?.get(1)
val Civ = matched?.get(2)
if (Name != null)
println(Name)
if (Civ != null)
println(Civ)
val newFileName = "$Name $Civ"
return#lit
}
Because you want to stop processing as soon as you find a match, I don't think forEachLine is the best choice. Instead you can use useLines, and combine it with first to stop processing once you get a match:
val regex = Regex(""""Name":(?<Name>"\w+").*?"Civ":(?<Civ>"\w+").*?"Team":0""")
fun readFileLineByLineUsingForEachLine(fileName: String) =
File(fileName).useLines { lines ->
val (name, civ) = lines
.map { regex.find(it) }
.filterNotNull()
.first()
.destructured
"$name $civ"
}
For the example you provided, this returns the string "xyz" "maur".
that's just a very little modification of the correct, helpful answer from Adam here https://stackoverflow.com/a/66654710/2891692
fun readFileLineByLineUsingForEachLine2(fileName: String) =
File(fileName).useLines { lines ->
val (name, civ) = lines
.map {
val regexString = """
"Name":(?<Name>"\w+").*?"Civ":(?<Civ>"\w+").*?"Team":0
""".trim()
var regex = Regex(regexString)
regex.find(it)
}
.filterNotNull()
.first()
.destructured
"$name $civ"
}

How to change the characters in a string in kotlin

I am trying to change the character in a string to some other character.
Here is my code
fun main(args: Array<String>) {
var str: String = "H...H"
for(i in 0..str.length-1) {
if( str[i] == '.')
str[i] = 'B'
}
println(ans)
}
But this produces the error:
jdoodle.kt:20:16: error: no set method providing array access
str[i] = 'B'
But the following code works fine:
fun main(args: Array<String>) {
var str: String = "H...H"
var ans : String = ""
for(i in 0..str.length-1) {
if( str[i] == 'H')
ans += str[i]
else if( str[i] == '.')
ans += 'B'
}
println(ans)
}
I just want to change all the ..... in the string to B.
Like "H...H" to "HBBBH"
Why is the first code not working?
The first example does not work because Strings in kotlin are immutable and you cannot change characters. Instead, you have to create a new String, like your second example (which, in fact, creates a new String for each time through the loop).
Kotlin has a replace function for you:
fun main() {
val input = "H...H"
val output = input.replace('.', 'B')
println(output) // Prints "HBBBH"
}

Kotlin replace multiple words in string

How to replace many parts of a string with something else in Kotlin using .replace()
For example, we can do it only by replacing one word
fun main(args: Array<String>) {
var w_text = "welcome his name is John"
println("${w_text.replace("his","here")}")
}
and the result will be " welcome here name is John " .
finally we need the result be " welcome here name is alles "
by replacing his to here and john to alles using .replace()
You can do it using multiple consecutive calls to replace():
w_text.replace("his", "here").replace("john", "alles")
You could write an extension that overloads String::replace:
fun String.replace(vararg replacements: Pair<String, String>): String {
var result = this
replacements.forEach { (l, r) -> result = result.replace(l, r) }
return result
}
fun main(args: Array<String>) {
val sentence = "welcome his name is John"
sentence.replace("his" to "here", "John" to "alles")
}
If you have many of those replacement rules, then create a mapping of them and call the replace method in a loop:
val map = mapOf("his" to "here", "john" to "alles", ...)
val sentence = "welcome his name is John"
var result = sentence
map.forEach { t, u -> result = result.replace(t, u) }
println(result)
For the ones interested in replacing a map of values in a text:
private fun replaceText(text: String, keys: Map<String, String>): String =
val replaced = map.entries.fold(text) { acc, (key, value) -> acc.replace(key, value) }
Here is a one liner:
fun String.replace(vararg pairs: Pair<String, String>): String =
pairs.fold(this) { acc, (old, new) -> acc.replace(old, new, ignoreCase = true) }
Test:
#Test fun rep() {
val input = "welcome his name is John"
val output = input.replace("his" to "her", "john" to "alles")
println(output)
output shouldBeEqualTo "welcome her name is alles"
}
Similar to other responses but using Kotlin extension and overloading String::replace to accept a map of oldValue to newValue.
fun String.replace(mapping: Map<String, String>): String {
var str = this
mapping.forEach { str = str.replace(it.key, it.value) }
return str
}
Usage:
val mapping = mapOf("his" to "here", "John" to "alles")
"his dad is John".replace(mapping) // here dad is alles
The issue with just using replace without any regex is:
Let's say I want to replace the occurrence of "here" with "there" inside the string "Where is my bag? Your bag is here." As you can imagine the result will be "Wthere is my bag? Your bag is there." which will not be correct. The solution is to use a regex like given below.
var str = "Where is my bag? Your bag is here."
val replacements = setOf("\\bhere\\b" to "there",
"\\bjohn\\b" to "alles")
replacements.forEach {
str = str.replace(Regex(it.first), it.second)
}