1

I want to check that each element in String is digit. Firstly, I split the String to an Array by a regexp [, ]+ expression and then I try to check each element by forall and isDigit.

object Test extends App {
  val st = "1, 434, 634, 8"

  st.split("[ ,]+") match {
    case arr if !arr.forall(_.forall(_.isDigit)) => println("not an array")
    case arr if arr.isEmpty                      => println("bad delimiter")
    case _                                       => println("success")
  }
}

How can I improve this code and !arr.forall(_.forall(_.isDigit))?

2
  • 1
    The array returned by split will never be empty. Commented Nov 14, 2019 at 7:00
  • what answer should be if you pass string 1 2 3, 123? And what do you mean by improve this code? Commented Nov 14, 2019 at 7:18

2 Answers 2

1

Use matches that requires the string to fully match the pattern:

st.matches("""\d+(?:\s*,\s*\d+)*""")

See the Scala demo and the regex demo.

Details

  • In a triple quoted string literal, there is no need to double escape backslashes that are part of regex escapes
  • Anchors - ^ and $ - are implicit when the pattern is used with .matches
  • The regex means 1+ digits followed with 0 or more repetitions of a comma enclosed with 0 or more whitespaces and then 1+ digits.
Sign up to request clarification or add additional context in comments.

4 Comments

Returns false for strings like " 1,2,4" and "1,2,4 ". Not sure if that's desired results or not.
@jwvh It is expected, see the sample input in the question that has no leading/trailing whitespace. Anyway, it can easily be added with \s* at the start and end of the pattern
Just curious: Why make it non-capture? What advantage does the ?: add?
@jwvh See Are non-capturing groups redundant?. In short: the best practice is to only use capturing groups only when you need to access part of the regex match after it occurred.
1

I think it can be simplified while also making it a bit more robust.

val st = "1,434 , 634   , 8"  //a little messier but still valid

st.split(",").forall(" *\\d+ *".r.matches)  //res0: Boolean = true

I'm assuming strings like "1,,,434 , 634 2 , " should fail.

The regex can be put in a variable so that it is compiled only once.

val digits = " *\\d+ *".r
st.split(",").forall(digits.matches)

1 Comment

nice approach @jwvh

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.