Format number based on pattern - kotlin

I need to format numbers based on pattern given in the code.
Number : 12038902.9, Pattern : "##,###,###.##". Output must be like : 12,038,902.9 I have to use this "##,###,###.##" & "##.###.###,##" also.
I have tried this but not working :
fun main() {
val number = 12038902.90
val pattern = "##,###,###.##"
val formattedNumber = formatNumber(number, pattern)
println(formattedNumber)
}
fun formatNumber(number: Double, pattern: String): String {
val parts = pattern.split(".")
val integerPart = parts[0].replace(",", "")
val decimalPartFormat = parts[1]
val intPartFormat = "%d"
val decimalPartForm = "%.${decimalPartFormat.length}f"
val formattedIntPart = String.format(intPartFormat, number.toInt()).replaceFirst("(?<=\\d)(?=(\\d{3})+(?!\\d))".toRegex(), ",")
val decimalPart = (number * 10.0.pow(decimalPartFormat.length)).toInt() % 10.0.pow(decimalPartFormat.length).toInt()
val formattedDecimalPart = String.format("%0${decimalPartFormat.length}d", decimalPart).replaceFirst("0*$".toRegex(), "").replaceFirst("(?<=\\d)(?=(\\d{3})+(?!\\d))".toRegex(), ",")
return "$formattedIntPart.$formattedDecimalPart"
}
Getting this output : 12,038902.9 which is wrong I want is 12,038,902.9:
Pattern & number both are dynamic so I need to adjust as per it's need.

maybe u can use DecimalFormat for this purpose. It takes care of grouping, proper separators etc.
Result for your the input 12038902.9 is: 12,038,902.9
fun convert(number: String) {
val decimalFormatSymbols = DecimalFormatSymbols()
decimalFormatSymbols.decimalSeparator = '.'
decimalFormatSymbols.groupingSeparator = ','
val decimalFormat = DecimalFormat()
decimalFormat.decimalFormatSymbols = decimalFormatSymbols
decimalFormat.groupingSize = 3
decimalFormat.maximumFractionDigits = 2
decimalFormat.minimumFractionDigits = 1
decimalFormat.maximumIntegerDigits = 8
decimalFormat.maximumIntegerDigits = 8
val formattedNumber = decimalFormat.format(number.toDoube())
println(formattedNumber)
}

Try with:
val number = 12038902.9
val pattern = "##,###,###.##"
val formattedNumber = DecimalFormat(pattern).format(number)

Related

Evaluating a string in kotlin

I wrote a code in kotlin for evaluating a given string from Divison to subtraction, it works but it gives the wrong answer, for example i got a string x in the first line which have answer -215.96666 whereas the answer from code is -237.366666 idk where the error is. i saw more people using stack for doing it, but i wanted to do this way for evaluating a string
var x : String = "5+4-10x20-40/30x20+34/20"
fun div(x: String): String {
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("/" in ele1) {
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for (ele2 in lis2) {
if ("/" in ele2) {
val pos3 = lis2.indexOf(ele2)
val lis3 = ele2.split("x").toMutableList()
for (ele3 in lis3) {
if ("/" in ele3) {
val pos4 = lis3.indexOf(ele3)
val lis4 = ele3.split("/")
val div = (lis4[0].toDouble() / lis4[1].toDouble()).toString()
lis3[pos4] = div
}
}
lis2[pos3] = lis3.joinToString("x")
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun mul(x : String) : String{
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if("x" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for(ele2 in lis2){
if("x" in ele2){
val pos2 = lis2.indexOf(ele2)
val lis3 = ele2.split("x")
val mul = (lis3[0].toDouble() * lis3[1].toDouble()).toString()
lis2[pos2] = mul
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun add(x : String): String {
val lis1 = x.split("-").toMutableList()
for(ele1 in lis1){
if("+" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+")
val add = (lis2[0].toDouble() + lis2[1].toDouble()).toString()
lis1[pos1] = add
}
}
return (lis1.joinToString("-"))
}
fun sub(x : String) : String{
val lis1 = x.split("-").toMutableList()
var sub = 0.0
for(ele1 in lis1){
sub -= ele1.toDouble()
}
return (sub.toString())
}
fun eval(x: String): String {
val divanswer = div(x)
val mulanswer = mul(divanswer)
val addanswer = add(mulanswer)
return sub(addanswer)
}
fun main(args: Array<String>){
println(eval(x))
}
i wanted the answer as -215.96666 but the answer given by code is -237.366666
In the case of this specific input, there are two bugs involved.
First bug is related to the fact you first process + and then -, but in mathematics we should process them together, from left to right. As a result, your algorithm processes this: 1-1+1 (correct answer: 1) as: 1-(1+1) (answer: -1). Alternatively, I believe handling - first and then + should work properly.
Second bug is that in sub() you start from 0 and subtract even the first number, but the first number should be actually added or used as an initial value.
I believe after fixing these two bugs, it should provide a correct answer for this specific input, but there are probably more bugs like these. For example, you incorrectly handle chains of the same operator, you only care about the first pair, so 1+1+1 becomes 2 (and then it is turned to -2 due to earlier mentioned bug).
As a general advice, learn to use a debugger and analyze how your data changes while your code is processing it. Even if you simply print your intermediate results: divanswer, mulanswer and addanswer and then run them through Google for processing, you will notice there is a problem somewhere at the add() step. Then rinse and repeat until everything works correctly.
Thanks to #broot for spotting this, the problem was with the addition and subtraction part, now that i merged them into one and got the correct answers for strings i input, here is the full code corrected.
var x : String = "5+4-10x20-40/30x20+34/20"
fun div(x: String): String {
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if ("/" in ele1) {
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for (ele2 in lis2) {
if ("/" in ele2) {
val pos3 = lis2.indexOf(ele2)
val lis3 = ele2.split("x").toMutableList()
for (ele3 in lis3) {
if ("/" in ele3) {
val pos4 = lis3.indexOf(ele3)
val lis4 = ele3.split("/")
val div = (lis4[0].toDouble() / lis4[1].toDouble()).toString()
lis3[pos4] = div
}
}
lis2[pos3] = lis3.joinToString("x")
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun mul(x : String) : String{
val lis1 = x.split("-").toMutableList()
for (ele1 in lis1) {
if("x" in ele1){
val pos1 = lis1.indexOf(ele1)
val lis2 = ele1.split("+").toMutableList()
for(ele2 in lis2){
if("x" in ele2){
val pos2 = lis2.indexOf(ele2)
val lis3 = ele2.split("x")
val mul = (lis3[0].toDouble() * lis3[1].toDouble()).toString()
lis2[pos2] = mul
}
}
lis1[pos1] = lis2.joinToString("+")
}
}
return (lis1.joinToString("-"))
}
fun final(x: String): Double {
val substr = StringBuffer()
var answer = 0.0
var opr = '+'
for(ele in x.indices){
var current = x[ele]
if(current in '0'..'9' || current == '.'){
substr.append(current)
}
if(current == '-' || current == '+'){
var operand = substr.toString().toDouble()
substr.setLength(0)
when (opr){
'+' -> answer += operand
'-' -> answer -= operand
}
opr = current
}
}
val num = substr.toString().toDouble()
when(opr){
'+' -> answer += num
'-' -> answer -= num
}
return answer
}
fun eval(x: String): Double {
val divanswer = div(x)
return final(mul(divanswer))
}
fun main(args: Array<String>){
println(eval(x))
}

How to add spaces between numbers with Kotlin

How can I format string "2000000.00" into "2 000 000.00" with Kotlin?
You can do this with DecimalFormat():
val dec = DecimalFormat(<pattern> [, <optional, but recommended locale>])
and then replace , with :
val number = 2000000.00
val dec = DecimalFormat("###,###,###,###,###.00", DecimalFormatSymbols(Locale.ENGLISH))
val formattedNumber = dec.format(number).replace(",", " ")
println(formattedNumber)
.00 is needed to keep the digits!!!
This will print:
2 000 000.00
here as a test:
#Test
fun testDecimalFormat() {
val number = 2000000.00
val dec = DecimalFormat("###,###,###,###,###.00", DecimalFormatSymbols(Locale.ENGLISH))
val formattedNumber = dec.format(number).replace(",", " ")
assertThat(formattedNumber).isEqualTo("2 000 000.00")
}
#Test
fun testDecimalFormatWithDigitValue() {
val number = 2000000.01
val dec = DecimalFormat("###,###,###,###,###.00", DecimalFormatSymbols(Locale.ENGLISH))
val formattedNumber = dec.format(number).replace(",", " ")
assertThat(formattedNumber).isEqualTo("2 000 000.01")
}
Link: https://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html

Remove character or word from string in 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() }

Kotlin Creating List<List<Map<String, String>>>

I am trying to return List<List<Map<String, String>>> from a function in kotlin. I'm new to kotlin.
Edit1
Here's how I am attempting to to this
val a = mutableListOf(mutableListOf(mutableMapOf<String, String>()))
The problem with the above variable is, I am unable to figure out how to insert data into this variable. I tried with this:
val a = mutableListOf(mutableListOf(mutableMapOf<String, String>()))
val b = mutableListOf(mutableMapOf<String, String>())
val c = mutableMapOf<String, String>()
c.put("c", "n")
b.add(c)
a.add(b)
This is giving me:
[[{}], [{}, {c=n}]]
What I want is [[{c=n}]]
Can someone tell me how I can insert data into it?
The end goal I am trying to achieve is to store data in the form of List<List<Map<String, String>>>
EDIT 2
The function for which I am trying to write this dat structure:
fun processReport(file: Scanner): MutableList<List<Map<String, String>>> {
val result = mutableListOf<List<Map<String, String>>>()
val columnNames = file.nextLine().split(",")
while (file.hasNext()) {
val record = mutableListOf<Map<String, String>>()
val rowValues = file.nextLine()
.replace(",(?=[^\"]*\"[^\"]*(?:\"[^\"]*\"[^\"]*)*$)".toRegex(), "")
.split(",")
for (i in rowValues.indices) {
record.add(mapOf(columnNames[i] to rowValues[i]))
print(columnNames[i] + " : " + rowValues[i] + " ")
}
result.add(record)
}
return result
}
You don't need to use mutable data structures. You can define it like this:
fun main() {
val a = listOf(listOf(mapOf("c" to "n")))
println(a)
}
Output:
[[{c=n}]]
If you wanted to use mutable data structures and add the data later, you could do it like this:
fun main() {
val map = mutableMapOf<String, String>()
val innerList = mutableListOf<Map<String, String>>()
val outerList = mutableListOf<List<Map<String, String>>>()
map["c"] = "n"
innerList.add(map)
outerList.add(innerList)
println(outerList)
}
The output is the same, although the lists and maps are mutable.
In response to the 2nd edit. Ah, you're parsing a CSV. You shouldn't try to do that yourself, but you should use a library. Here's an example using Apache Commons CSV
fun processReport(file: File): List<List<Map<String, String>>> {
val parser = CSVParser.parse(file, Charset.defaultCharset(), CSVFormat.DEFAULT.withHeader())
return parser.records.map {
it.toMap().entries.map { (k, v) -> mapOf(k to v) }
}
}
For the following CSV:
foo,bar,baz
a,b,c
1,2,3
It produces:
[[{foo=a}, {bar=b}, {baz=c}], [{foo=1}, {bar=2}, {baz=3}]]
Note that you can simplify it further if you're happy returning a list of maps:
fun processReport(file: File): List<Map<String, String>> {
val parser = CSVParser.parse(file, Charset.defaultCharset(), CSVFormat.DEFAULT.withHeader())
return parser.records.map { it.toMap() }
}
Output:
[{foo=a, bar=b, baz=c}, {foo=1, bar=2, baz=3}]
I'm using Charset.defaultCharset() here, but you should change it to whatever character set the CSV is in.

reference a local variable from string

Is there a way that I could represent a local variable name by passing a string to represent the variable name?
for example something like this
val arr1 = arrayOf(1,2,3,"Apple")
val arr2: Array<Int> = Array(6,{i -> i * 2})
val arr3: Array<Int> = Array<Int>(6,{i -> i+1})
val arr4 = arrayOf<Int>(1,2,3)
for (i in 1..4){
val arrResult = java.util.Arrays.deepToString("arr${i}")
println(arrResult)
}
Such question usually means that you want to use dictionaries. In this case an array suffices:
fun main() {
val arr0 = arrayOf(1,2,3,"Apple")
val arr1: Array<Int> = Array(6,{i -> i * 2})
val arr2: Array<Int> = Array<Int>(6,{i -> i+1})
val arr3 = arrayOf<Int>(1,2,3)
val arrs = arrayOf(arr0, arr1, arr2, arr3)
for (i in 0..3) {
val arrResult = java.util.Arrays.deepToString(arrs[i])
println(arrResult)
}
}