format six digit numeric number comma separated in mule 4 - mule

I am having the below payload
{
"data": {
"Final_band": {
"min": "229573",
"max": "292184"
}
},
"message": "Engine pricing details fetched successfully"
}
Now I am trying to format the values "min": "229573" and "max": "292184" into something like 2,29,573 and 2,92,184.
The problem is I am trying every solution, but I am not getting the desired result
%dw 2.0
import * from dw::util::Values
var minV = round(payload.data.Final_band.min as Number ) as String {format: "#,##,###"}
var maxV = round(payload.data.Final_band.max as Number) as String {format: "#,##,###"}
output application/json
---
{
"Final_band": {
"min": minV,
"max": maxV
}
}
Firstly, I am rounding off the numeric values, and then I coercing the same into string and then applying format: "#,##,###"
but it outputs the "min":"229,573" and "max": "292,184"
it is working fine for format: "#,#####"
i,e "min":"2,29573" and "max": "2,92184"
but when I add more comma(,) for thousand place, it won't work as expected

The formatting of number in Dataweave is based on java.text.DecimalFormat (reference). Which does not support variable width groups. I only see you have two options.
You will either have to use another 3rd party java library that can handle this and use Java module to invoke the required methods.
You can implement your own logic which is fairly easy for this in Dataweave. (Infact if you see in the other java question, most answers have suggested their own implementation)
%dw 2.0
output application/json
/**
* Strip the last digit of number. If decimal strip the number after decimal along with the last digit of whole number
* Format the remaining numbers with ##,##.
* Append the stripped part to this formatted number.
*/
fun indianFormatNum(num: Number) =
if(num >= 0 and num < 10) num // otherwise this will pad single digit numbers with a 0
else do {
//lets say input is 123456.78
var appendLater = (num mod 10) as String // value will be 6.78
var remainingNumner = floor(num / 10) // value will be 12345
---
remainingNumner as String {format: "##,##"} ++ appendLater
// 1,23,45 ++ 6.78
}
---
{
a: indianFormatNum(12345), // outputs 12,345
b: indianFormatNum(123457.89), // outputs 1,23,457.89
c: indianFormatNum(8)
}

Related

How do we round only if the number is with .0 in decimal

Ex 10.0 = 10
10.3 = 10.3
10.7 = 10. 7
Looking for a convenient way from Kotlin Standard library
You can use the following function:
fun removeTrailingZeros(num: String): String {
if(!num.contains('.')) // Return the original number if it doesn't contain decimal
return num
return num
.dropLastWhile { it == '0' } // Remove trailing zero
.dropLastWhile { it == '.' } // Remove decimal in case it's the last character in the resultant string
}
You can verify the code here
You can try this:
double number = 23.471;
if (number % 1 != 0)
{
//round off here
System.out.print ("Decimal");
}
else
{
System.out.print ("Integer");
}
If you want to get a string, the easiest way is to work with a string like num.toString().replace(".0",""). For numbers conversion does not make sense since the resulting type is different for different inputs.

Kotlin convert hex string to ByteArray

I have this string:
val s = "00b44a0bc6303782b729a7f9b44a3611b247ddf1e544f8b1420e2aae976003219175461d2bd7" +
"6e64ba657d7c9dff6ed7b17980778ec0cbf75fc16e52463e2d784f5f20c1691f17cdc597d7a514108" +
"0809a38c635b2a62082e310aa963ca15953894221ad54c6b30aea10f4dd88a66c55ab9c413eae49c0b" +
"28e6a3981e0021a7dcb0759af34b095ce3efce78938f2a2bed70939ba47591b88f908db1eadf237a7a" +
"7100ac87130b6119d7ae41b35fd27ff6021ac928273c20f0b3a01df1e6a070b8e2e93b5220ad0210400" +
"0c0c1e82e17fd00f6ac16ef37c3b6153d348e470843a84f25473a51f040a42671cd94ffc989eb27fd42" +
"b817f8173bfa95bdfa17a2ae22fd5c89dab2822bcc973b5b90f8fadc9b074cca8f9365b1e8994ff0bda48" + "b1f7498cce02d4e794915f8a4208de3eaf9fbff5"
Which is hexadecimal notation of bytes, hardcoded in as string format.
I need this thing as a bytearray, importantly, not the ASCII representation of it, actually the hexadecimal values that is represents.
All the kotlin methods I can find, such as:
val b = s.encodeToByteArray()
Seem to be taking the actual ASCII value of the string, and converting it to a bytearray.
How do I create a bytearray directly from the values in this string?
You can handle it like this:
fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
return chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
}
Split the string into 2-character pairs, representing each byte.
Parse each hex pair to their integer values.
Convert the parsed Ints to Bytes.
My other answer is the simplest way, but it creates two intermediate lists - a list of strings and a list of bytes - before it creates the byte array. Here are two slightly more complex versions that are more efficient.
This version uses sequences to take advantage of lazy evaluation. It still produces a string for every byte, but uses no intermediate lists.
fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
val byteIterator = chunkedSequence(2)
.map { it.toInt(16).toByte() }
.iterator()
return ByteArray(length / 2) { byteIterator.next() }
}
This version uses the JDK's java.lang.Integer.parseInt function. It creates the ByteArray directly with no intermediate data-structures.
fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
return ByteArray(length / 2) {
Integer.parseInt(this, it * 2, (it + 1) * 2, 16).toByte()
}
}

Format a number to string, fill 0 when it's not enough two characters

I want to format the number to String and fill 0 when it's not enough two characters
fun formatDuration(val duration):String {
val minutes = duration.toInt() / 60
return "$minutes"
}
For example, if minutes is 6, it should displayed 06 rather than 6.
You can padStart the toString() result of minutes.
I tried your code in the Kotlin Playground and it wasn't compilable / runnable. For the following example, I had to change parts of your fun:
fun main() {
println(formatDuration(364.34))
}
fun formatDuration(duration: Double): String {
val minutes = duration.toInt() / 60
// fill the result to be of 2 characters, use 0 as padding char
return minutes.toString().padStart(2, '0')
}
Executing this results in the output 06.
Alternatively, you can simply use String.format() from Java, just
return "%02d".format(minutes)
instead of return minutes.toString().padStart(2, '0'), the result stays the same.
You can achive this with padStart
Example:
val padWithSpace = "125".padStart(5)
println("'$padWithSpace'") // ' 125'
val padWithChar = "a".padStart(5, '.')
println("'$padWithChar'") // '....a'
// string is returned as is, when its length is greater than the specified
val noPadding = "abcde".padStart(3)
println("'$noPadding'") // 'abcde'

Add commas or point every 3 digits using kotlin

I want to add commas or point every 3 digit in EditText input.
Example :
input : 1000. Output : 1.000
input : 11000. Output : 11.000
If you are on the JVM you can use
"%,d".format(input)
which gives 11,000 for input 11000. Replace , with any delimiter you require.
If you want to use predefined number formats, e.g. for the current locale, use:
java.text.NumberFormat.getIntegerInstance().format(input);
Be also sure to check the other format instances, e.g. getCurrencyInstance or getPercentInstance. Note that you can use NumberFormat also with other locales. Just pass them to the get*Instance-method.
Some of the second variant can also be found here: Converting Integer to String with comma for thousands
If you are using it via Javascript you may be interested in: How do I format numbers using JavaScript?
Based on Splitframe answer above, did a simplified version (without the var):
fun Int.formatDecimalSeparator(): String {
return toString()
.reversed()
.chunked(3)
.joinToString(",")
.reversed()
}
And added some tests:
#Test
fun whenFormatDecimal_thenReturnFormatted() {
mapOf(
1 to "1",
12 to "12",
123 to "123",
1234 to "1,234",
12345 to "12,345",
123456 to "123,456",
1234567 to "1,234,567",
12345678 to "12,345,678",
123456789 to "123,456,789",
1234567890 to "1,234,567,890",
).forEach { (test, expected) ->
val result = test.formatDecimalSeparator()
assertEquals(expected, result)
}
}
In my case is a KMM project, and we don't support other languages, so it does the job. A better solution I would say to create an expect Util class and each platform implement the formatter taking account of the user Locale, etc.
System.out.println(NumberFormat.getNumberInstance(Locale.US).format(35634646));
This is a simple way that able you to replace default separator with any characters:
val myNumber = NumberFormat.getNumberInstance(Locale.US)
.format(123456789)
.replace(",", "،")
I used this for a non JVM Kotlin environment:
fun formatDecimalSeperators(number :String) :String {
var index = 1
return number
.takeIf { it.length > 3 }
?.reversed()
?.map { if (index++ % 3 == 0) "$it," else it }
?.joinToString("")
?.reversed()
?.removePrefix(",")
?: number
}
You can also use #Roland answer in Android String Resources to format it:
<string name="answer_count">%,01d answers</string>
For a method without getting Locale, you can use an extension to convert your Int into a formatted String like this below :
fun Int.formatWithThousandComma(): String {
val result = StringBuilder()
val size = this.toString().length
return if (size > 3) {
for (i in size - 1 downTo 0) {
result.insert(0, this.toString()[i])
if ((i != size - 1) && i != 0 && (size - i) % 3 == 0)
result.insert(0, "\'")
}
result.toString()
} else
this.toString()
}

Specman - Assign uint decimal number to sequence

I have the following sequence:
extend CONFIG_ADC_CLK ocp_master_sequence_q {
divide_by : uint(bits:4);
align_by : uint(bits:4);
body()#driver.clock is {
var div : uint(bits:3);
case divide_by {
1 : { div = 0; };
2 : { div = 1; };
4 : { div = 2; };
8 : { div = 3; };
16 : { div = 4; };
default : { dut_error(divide_by," is not a legal Clock division for ADC"); };
};
gad_regs.gad_clk_gen.clk_algn = align_by;
gad_regs.gad_clk_gen.clk_dev = div;
do WR_REG seq keeping {.reg==gad_regs.gad_clk_gen;};
};
};//extend CONFIG_ADC_CLK ocp_master_sequence_q {
In the test I use the sequence :
do CONFIG_ADC_CLK seq keeping {.divide_by== 3;.align_by==0;};
For some reason the compiler refer the number of the field divide_byas hex number instead of decimal.
How can I ensure that it will refer it as decimal?
This is not related to sequences and not related to how numbers are assigned to fields. It's just about how numeric values are formatted in printing and string operations. The actual value of a field has nothing to do with how it is printed.
By default, dut_error(), message(), out(), append() and other string formatting routines use the current setting of config print -radix. So, you probably have it set to HEX in your environment.
If you need this specific dut_error() to always use decimal format, no matter what the config setting is, you can use dec(), like this:
dut_error(dec(divide_by)," is not a legal Clock division for ADC");
By the way, when using the second variant of those routines, such as dut_errorf() or appendf(), you can determine the radix by providing the right % parameter, e.g., %d for decimals or %x for hexa, for example, the above dut_error() might be rewritten as:
dut_errorf("%d is not a legal Clock division for ADC", divide_by);
Here, you can also use %s, in which case the config radix setting is still used.