How to get String description/value? - kotlin

In Kotlin, how to get the raw value of the String?
For example,
val value: String = "Adrian"
Expected result:
"Cannot find value: Adrian"
I am coming from Swift and I know in swift it works like this
let value: String = "Adrian"
print("Cannot find \(string.description): \(value)")
Another example in Swift,
let a: String = "b"
print("\(a.description) = \(a)"
///prints "a = b"
Im guessing a String extension is needed given I read the Kotlin String documentation and seems none of the choices provides the expected result.
A simple problem but I really can't solve it:(

This might help you. For this you have to use Kotlin reflection:
Example:
data class Person(val name:String)
fun main(){
val person = Person("Birju")
val prop = person::name
println("Property Name: ${prop.name}")
println("Property Value: ${prop.get()}")
}

How about
println("value :$value")
You don't need concatination operator(+) to concat strings in kotlin

Related

Kotlin Generic problem, UNCHECKED_CAST , required:Nothing

#file:Suppress("UNCHECKED_CAST")
data class Element<T>(
val key: String,
val valueOne: T,
val valueTwo: T,
val comparator: Comparator<T>,
val comparatorValue: CompareResult
)
enum class CompareResult(
val value: Int
) {
LESS(-1),
EQUAL(0),
GREATER_THAN(1)
}
fun <T> matchesComparison(list:Collection<Element<T>>): Pair<Boolean, List<String>> {
val failedComparisons = mutableListOf<String>()
for (element in list) {
val compareValue = element.comparator.compare(element.valueOne, element.valueTwo)
if (element.comparatorValue.value != compareValue) {
failedComparisons.add(element.key)
}
}
return Pair(failedComparisons.isEmpty(), failedComparisons)
}
val stringComparator = Comparator.comparing(String::toString)
val intComparator = Comparator.comparing(Int::toInt)
val elementsToCompare = listOf(
Element("number", 1, 2, intComparator, CompareResult.LESS),
Element("first name", "a", "a", stringComparator, CompareResult.EQUAL),
Element("last name", "a", "b", stringComparator, CompareResult.EQUAL)
)
matchesComparison(elementsToCompare).second.joinToString(", ","Failed elements: \"","\"")
I often get faced with comparing two different object properties with the same values.
As an example object A has props number,firstname,lastname. What i want to do is create a list have and have a function which goes over these Elements and returns which props have failed the comparison. I've managed to use generics for both the object and the matchesComparison function which returns the failed comparisons. The problem begins when i want to pass this list which is of type Collection<Element<out Any>> to this function is i get a type missmatch. instead of using unchecked casts to force the Comparator to be of type Any i would like to do this
val stringComparator = Comparator.comparing(String::toString)
val intComparator = Comparator.comparing(Int::toInt)
The result value that of the script above should be Failed elements: "last name"
I tried changing the signature of the function to out any but then the comparator.compare method has both params as of type Nothing. I really want to avoid unsing unchecked casts.
matchesComparison() doesn't need to be generic in this case. It doesn't really care what is the type of the whole input collection, so we can simply use * here.
Then we have another problem. The compiler isn't smart enough to notice that while we perform operations on a single element, all its properties are of matching types. As a result, it doesn't allow to use element.comparator on element.valueOne and element.valueTwo. To fix this problem, we simply need to create a separate function which works on a single Element, so it understand the type for all properties is the same:
fun matchesComparison(list:Collection<Element<*>>): Pair<Boolean, List<String>> {
fun <T> Element<T>.matches() = comparatorValue.value == comparator.compare(valueOne, valueTwo)
val failedComparisons = mutableListOf<String>()
for (element in list) {
if (!element.matches()) {
failedComparisons.add(element.key)
}
}
return Pair(failedComparisons.isEmpty(), failedComparisons)
}
Also, I believe such matches() function should be actually a member function of Element. It seems strange that while Element is pretty independent and it contains everything that is needed to perform a comparison, it still requires to use external code for this. If it would have a matches() function then we wouldn't need to care about its T. matches() would work with any Element.

Why am I geting a blank when I run this string funtion in Kotlin?

So I was solving a problem that required me to put unique characters in a string without using a data structure.
fun main(){
val s1 = "fhfnfnfjuw"
val s2 = "Osayuki"
val s3 = "Raymond"
val s4 = "Aseosa"
uniqueChar(s1)
}
fun uniqueChar(s: String){
val updatedString = ""
s.forEach {c ->
if (!updatedString.contains(c)){
updatedString.plus(c)
}
}
println(updatedString)
}
And getting this error
I'm not sure what's going on and why I'm getting a blank. I'm sure it's an easy fix, but I can't see it. Any help is appreciated.
updatedString.plus(c) does not change updatedString. It creates a new string, including the character c. Since you don't do anything with that, the new string goes...nowhere.
Instead, you probably wanted updatedString = updatedString.plus(c) -- or something better with StringBuilder, but that's the closest version to your code.

TypeVariable(V) Required in Mutable Map assignment in Kotlin. Cannot put the value from a map to itself

The following example is a simplified version of what I am trying to do in my application.
fun main() {
val test: MutableMap<Int, String> = mutableMapOf(
1 to "Apple",
)
test[2] = test[1] // test[1] has incorrect type.
}
The code doesn't compile. IntelliJ gives the following hint:
Type mismatch.
Required: TypeVariable(V)
Found: String?
I don't understand what a TypeVariable is. but when I provide a default value the error disappears
test[2] = test[1] ?: "Grape"
Why the required type is TypeVariable(V), not String, and what exactly is it? What to do if there's no default value for my application purposes?
... = test[1]
returns a String? as the hint showed you. But test is a MutableMap of <Int, String>, which means you need to assign a String:
... = test[1]!!
Of course this will only work if 1 is a valid key in test. Otherwise your code with the null safety operator is the way to go:
... = test[1] ?: "default value"

Using map function to transform an item in a list

Kotlin 1.4.21
I have a list of Products and I want to transform the price to a formatted string. However, the price doesn't change to the formatted one.
i.e.
orginal price: 1658
expected: "1,658.00"
actual: 1658
This is the class structure
data class Product(
val productName: String,
val price: Double)
Here I am using my list of projects and I want to transform the price.
listOfProjects.map {
it.price.toAmount(2) // extension function that formats to 2 decimal places and converts to a string
}
if (listOfProjects.isNotEmpty()) {
// Do something with the list. However, the price hasn't changed
}
You probably are expecting it to perform in-place formatting. Maybe if you assign an output variable you would be able to get it:
val result = listOfProjects.map { it.price.toAmount(2) }
println(result)
Or if you add a val formattedPrice: String property on the Project class you can define it like this:
val formattedPrice: String = price.toAmount(2)
and then you can use this property in a toString() method for example.
Have you ever tried :
import java.text.DecimalFormat
val dec = DecimalFormat("###.###,##")

Decimal format in kotlin

Is it possible to use a method or something else rather “%.6f”.format(value) in order to achieve the same thing?
this is my code :
println("%.6f".format(value))
I'll want to make it more dynamic and readable
You can always use
String.format("%.6f", value)
But you can extract the format in a variable
val FORMAT_FLOAT = "%.6f"
println(String.format(FORMAT_FLOAT, value))
It depends on your preferences. Good luck!
You can make it an Extension Function for your project, which is a very powerful feature of Kotlin, the function is like this:
fun Double.roundDecimal(digit: Int) = "%.${digit}f".format(this)
Just put it in a Kotlin file But Outside The Class, then you can access it everywhere in your project:
fun main() {
val number = 0.49555
println(number.roundDecimal(2))
println(number.roundDecimal(3))
}
Output:
0.50
0.496
you can use DecimalFormat class to round a given number. More info
i.e.
val num = 1.345672
val df = DecimalFormat("#.######")
df.roundingMode = RoundingMode.CEILING
println(df.format(num))