0

So i have this string:

val value = "\nValue is €2,927"

How can i parse this amount 2927, of any currency, and convert it to double/int ?

This is what i have try:

println(value.replaceAll("d{5}", ""))

Edit:

could be any currency sign.

SamWhan
  • 8,296
  • 1
  • 18
  • 45
david hol
  • 1,272
  • 7
  • 22
  • 44

2 Answers2

2

This may not be a definitive answer to your question (I'm not a Scala coder) but I think it'll be useful anyway, combined with other answers and comments.

You made me think about creating a regex to identify monetary amounts only, ignoring other numbers. This is what I came up with:

([$£€¥₹])?(\d{1,3}(?:[, ]?\d{1,3})?(?:.\d+)?)(?(1)|(kr\.?|Kč))

This example handles amounts pre-fixed with signs for dollars $, GB pounds £, Euro , Japanese Yen (or Chinas Yuan Renminbi (?)) ¥ or Indian rupees .

It also handles currencies with a post-fixed currency "symbol". In the example Swedish/Danish/Norwegian kronor kr and Czech koruna .

The amount is always captured in capture group 2. A prefixed currency symbol is in group 1, and a postfixed in group 3. (I figured - what good is the amount if you don't know the currency.)

See it here at regex101, handling this text:

The cost of this car with a 3.5 litre engine, is €2,927.100, or $3 271.32. In Sweden that would be around 27000kr. I would have to work overtime for 215 days to save the money for that, even though my job in the Czech Republic pays 436.5Kč an hour, and I can save 10% percent of that. My buddy in Japan, bought one for ¥357014.83.

It starts by matching an optional currency sign. Then it matchers the amount, which can be formatted like any of ###, ##,###, ##,###,###.###. After that it uses a regex condition - if the initial currency symbol was matched, it matches nothing -> done. If it wasn't matched, it tests for the post-fixed currency types.

The code (shooting from the hip here - no Scala experience what so ever, just a "googler"):

val value = "\nValue is €2,927"
val pattern = "([$£€¥₹])?(\\d{1,3}(?:[, ]?\\d{1,3})?(?:.\\d+)?)(?(1)|(kr\\.?|Kč))".r
val pattern(c1, amnt, c2) = value
// remove spaces and thousands-separators from the value
val str = amnt.replaceAll("[ ,]", "")
// convert it to an integer and/or double.
val i = str.toInt
val d = str.toDouble

Edit

Wow! This was a tough one to crack. I've now learnt that java regex doesn't support if-else constructs. So here's an alternative, little bit more complicated alternative:

(?=[$£€¥₹])(.)(\d{1,3}(?:,\d{3})?(?:\.\\d+)?)|(\d{1,3}(?:,\d{3})?(?:\.\d+)?)(kr\.?|Kč)

It uses a positive look-ahead to determine if it's a pre-fixed, or a post-fixed currency symbol. The actual amount capturing had to be split into two groups depending on pre or post. So either currency is in group 1 and amount in 2, or amount in 3 and currency in 4.

And see functioning ;) code here at ideone.

Edit #2

Some new currencies and stuff added after comment.

(Rs.|[$£€¥₹])?\s*(\d{1,3}(?:[, ]?\d{1,3})?(?:.\d+)?)(?(1)|\s*(kr\.?|Kč|INR|€))

Here at regex101.

SamWhan
  • 8,296
  • 1
  • 18
  • 45
  • Was looking at your profile, and so the "most unappreciated" answer. The complexity of this regex throws me off ;) But to add a little more to it if you want, french people likes to do things not like everybody, and so, the currency is written with € post-fixed and thousands could be space separated ;) : ie `€2,927.100` would be written in France : `2 927,10€` or `2 927.10€` or `2927,10€` or `2927.10€` :D – Esteban Jun 29 '17 at 07:01
  • @Esteban Thanks! Fixed and added as examples. :) – SamWhan Jun 29 '17 at 08:21
  • 1
    Sorry to say this, but NOW I have but no choice to upvote it, and so making this answer no longer you "most unappreciated" :p – Esteban Jun 29 '17 at 09:13
0

You could have a similar solution from my my answer here. So:

scala> import scala.util.matching.Regex
import scala.util.matching.Regex

scala>  val matcher = new Regex("\\d{1,1}")
matcher: scala.util.matching.Regex = \d{1,1}

scala> val value = "\nValue is €2,927"
value: String =
"
Value is €2,927"

scala> matcher.findAllMatchIn(value).toList.mkString.toInt
res1: Int = 2927

EDIT: Should accommodate doubles...

scala> val value = "\nValue is €2,927.545"
value: String =
"
Value is €2,927.545"

scala>  val matcher = new Regex("\\d{1,3}[\\.\\,\\ ]?[0-9]$*")
matcher: scala.util.matching.Regex = \d{1,3}[\.\,\ ]?[0-9]$*
scala> matcher.findAllMatchIn(value).toList.mkString.replaceAll("[ ,]", "").toDouble
res7: Double = 2927.545

And for spaces...

scala> val value = "\nValue is €2 927, 927.545"
value: String =
"
Value is €2 927, 927.545"

scala> matcher.findAllMatchIn(value).toList.mkString.replaceAll("[ ,]", "").toDouble
res8: Double = 2927927.545
Community
  • 1
  • 1
airudah
  • 1,169
  • 12
  • 19