How to change every letter in a word using dictionary? - kotlin

So basically the title I want to change the word letters to another word but it says I have to specify the parameter
fun main() {
val dictionary = mapOf( "c" to "b", "a" to "d" , "r" to "e"//here is the letters i want to change
)
val letters = "car"//the word i want to change
for (me in letters){
println(dictionary[me])
}
}
i want for "car" to be "bde"

Notice that your map has strings as keys, because you used string literals in these places:
val dictionary = mapOf( "c" to "b", "a" to "d" , "r" to "e")
*** *** ***
However, when you access the map, you are accessing it using me, which is a Char you got from the string letters. This causes the error.
I would suggest that you change the map to use Char keys instead. Change the string literals to character literals:
val dictionary = mapOf( 'c' to "b", 'a' to "d" , 'r' to "e")
*** *** ***
Notice that the letters are now surrounded with single quotes.
Though it is not required to solve this particular problem, you can also change the map's values to character literals too.
After that, you should use print instead of println to print the map values out, so that they are all printed on the same line:
for (me in letters){
print(dictionary[me] ?: me.toString())
}
Note that I added the ?: me.toString() part so that if no replacement was found in the map, the original letter would be printed.
If you want a single string as the result, rather than having it printed out,
val result = letters.map { dictionary[it] ?: it.toString() }.joinToString("")

Related

parse string to an array in Kotlin

How can I convert a string to an array of strings in Kotlin? To demonstrate, I have this:
val input_string = "[Hello, World]"
I would like to convert it to ["Hello", "World"].
Assuming that the array elements do not contain commas, you can do:
someString.removeSurrounding("[", "]")
.takeIf(String::isNotEmpty) // this handles the case of "[]"
?.split(", ")
?: emptyList() // in the case of "[]"
This will give you a List<String>. If you want an Array<String>:
someString.removeSurrounding("[", "]")
.takeIf(String::isNotEmpty)
?.split(", ")
?.toTypedArray()
?: emptyArray()
Assuming the strings only consist of letters and/or numbers you could also do it like this
val input_string = "[Hello, World]"
val list = Regex("\\w+").findAll(input_string).toList().map { it.value }

How do I replace letters with numbers using the replace function in kotlin inside a lambda expression

mood = "leet"
modifier = { message ->
val regex = """(L|e|t)""".toRegex()
//Clueless about what to do after this
}
THIS IS WHAT I CAME UP WITH SO FAR, THE QUESTION IN THE BOOK BIG NERD RANCH KOTLIN EDITION 2 SAYS "leet (or 1337): The narrator will speak in leetspeak, replacing letters with numbers and symbols that look similar. For example, ‘L’ becomes ‘1’; ‘E’ becomes ‘3’; ‘T’ becomes ‘7’. (Hint: Take a look at String’s replace function. There is a version that accepts a lambda as the second parameter.)"
This is the function they're telling you to look at, specifically this one:
inline fun CharSequence.replace(
regex: Regex,
noinline transform: (MatchResult) -> CharSequence
): String
Returns a new string obtained by replacing each substring of this char sequence that matches the given regular expression with the result of the given function transform that takes MatchResult and returns a string to be used as a replacement for that match.
So the lambda you provide is a function that takes a MatchResult
and does something with it, and returns a CharSequence (which can be a one-character long String). The replace function calls that lambda for every match that regex makes.
You get the general idea of what you're supposed to do? You have two parts here - the thing that identifies parts of the input string to process, and the thing that takes those matches and changes them into something else. The result is the original string with those changes made. So you need to come up with a regex and a transform that work together.
Nobody (probably) is going to tell you the answer because the point is figuring it out for yourself, but if you have any questions about things like regexes people will be happy to help you out! And speaking of, this site is extremely useful (I just used it myself to check I knew what I was doing): https://regex101.com/
Here is the implementation as pointed by #cactustictacs :
5 -> {
mood = "leet"
val regex: Regex = """[LET]""".toRegex()
modifier = { message ->
message.uppercase().replace(regex) { m ->
when (m.value) {
"L" -> "1"
"E" -> "3"
"T" -> "7"
else -> ""
}
}
}
}
and here is the another method almost same but with minor change using regex.replace()
5 -> {
mood = "leet"
val regex: Regex = """[LET]""".toRegex()
modifier = { message ->
regex.replace(message.uppercase()){m ->
when (m.value) {
"L" -> "1"
"E" -> "3"
"T" -> "7"
else -> ""
}
}
}
}
You can use it in place of m to make it slightly more concise.

Take string if not empty not working as expected

I have a fun that replaces comma with empty string. Then converts it to double. User can input only numbers and commas. After replace I want to take this string only if its not empty for conversion purposes. But although its empty takeIf{} doesnt seem to see it this way. When I enter only "," as first char in a string, the conversion fails throwing:
java.lang.NumberFormatException: empty String
Scenario when entering , as first char.
replace(",", "")
.takeIf {
println(it) //prints nothing
println(it.length) //prints 0
if (isNotEmpty()) { // docs says that it checks if length > 0, which is not, so string is empty
println("not empty") // still prints not empty
} else {
println("empty")
}
isNotEmpty()
}?.toDouble()) // runs toDouble on empty string
Logs:
System.out: 0
System.out: not empty
Note that replace returns the adapted String, but does not alter the underlying string... So when you call isNotEmpty() you check for the initial/receiver String (which was ","), but when you print the content or the length, you take the result of the replacement (it).
So if you use it consequently, it will work as you expect.
Note also that there exists toDoubleOrNull() which just returns null if no double can be extracted from the String, e.g:
replace(",", "").toDoubleOrNull() // if it is not parseable, we get null
So you can spare even more characters and conditions in your code.

Checking if string is empty in Kotlin

In Java, we've always been reminded to use myString.isEmpty() to check whether a String is empty. In Kotlin however, I find that you can use either myString == "" or myString.isEmpty() or even myString.isBlank().
Are there any guidelines/recommendations on this? Or is it simply "anything that rocks your boat"?
Thanks in advance for feeding my curiosity. :D
Don't use myString == "", in java this would be myString.equals("") which also isn't recommended.
isBlank is not the same as isEmpty and it really depends on your use-case.
isBlank checks that a char sequence has a 0 length or that all indices are white space. isEmpty only checks that the char sequence length is 0.
/**
* Returns `true` if this string is empty or consists solely of whitespace characters.
*/
public fun CharSequence.isBlank(): Boolean = length == 0 || indices.all { this[it].isWhitespace() }
/**
* Returns `true` if this char sequence is empty (contains no characters).
*/
#kotlin.internal.InlineOnly
public inline fun CharSequence.isEmpty(): Boolean = length == 0
For String? (nullable String) datatype, I use .isNullOrBlank()
For String, I use .isBlank()
Why? Because most of the time, I do not want to allow Strings with whitespace (and .isBlank() checks whitespace as well as empty String). If you don't care about whitespace, use .isNullorEmpty() and .isEmpty() for String? and String, respectively.
Use isEmpty when you want to test that a String is exactly equal to the empty string "".
Use isBlank when you want to test that a String is empty or only consists of whitespace ("", " ").
Avoid using == "".
There are two methods available in Kotlin.
isNullOrBlank()
isNullOrEmpty()
And the difference is:
data = " " // this is a text with blank space
println(data.isNullOrBlank()?.toString()) //true
println(data.isNullOrEmpty()?.toString()) //false
You can use isNullOrBlank() to check is a string is null or empty. This method considers spaces only strings to be empty.
Here is a usage example:
val s: String? = null
println(s.isNullOrBlank())
val s1: String? = ""
println(s1.isNullOrBlank())
val s2: String? = " "
println(s2.isNullOrBlank())
val s3: String? = " a "
println(s3.isNullOrBlank())
The output of this snippet is:
true
true
true
false
As someone mentioned in the comments, you can use ifBlank, like so:
fun getSomeValue(): String {
// ...
val foo = someCall()
return foo.ifBlank { "some-default" }
}
Documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/if-blank.html

Reduce List to longest String in the List with Elm

I'm trying to figure out how to create a function that takes a List of Strings and returns a new list that only contains the longest string in the list.
I'm having a hard time figuring out several aspects of this problem including how to keep track of the maximum and change it when there is a new longest string. Do I need to use an Effect / Task?
Example: a function that takes ["one", "two", "three"] and returns ["three"] since it is the longest string.
If you just want a function that gives you the longest string of a list:
List.sortBy String.length >> List.reverse >> List.take 1
You could fold your list, keeping track of the longest string along the way:
import String exposing (length)
findLongest = List.foldr (\x y -> if length x > length y then x else y) ""
This has a performance advantage over List.sortBy, since foldr is taking a single swipe at the list, while sorting has to sort all the items.
Good news: You don't need to use an Effect or Task.
A longest string function can be defined as follows:
import String exposing (length)
longerString : String -> String -> String
longerString s1 s2 = if length s2 > length s1 then s2 else s1
longestString : List String -> String
longestString = List.foldr longerString ""
Then you can use it like:
longestString ["one", "two", "three"] -- returns "three"
If you want the result as a list with one element, that is also possible.
[ longestString [ "one", "two", "three" ] ] -- returns [ "three" ]