11

I need to process phone numbers using regex and group them by (country code) (area code) (number). The input format:

country code: between 1-3 digits , area code: between 1-3 digits , number: between 4-10 digits

Examples:

1 877 2638277
91-011-23413627

And then I need to print out the groups like this:

CC=91,AC=011,Number=23413627

This is what I have so far:

String s = readLine
val pattern = """([0-9]{1,3})[ -]([0-9]{1,3})[ -]([0-9]{4,10})""".r
val ret = pattern.findAllIn(s)
println("CC=" + ret.group(1) + "AC=" + ret.group(2) + "Number=" + ret.group(3));

The compiler said "empty iterator." I also tried:

val (cc,ac,n) = s

and that didn't work either. How to fix this?

2
  • It's a bad idea to do this splitting. For example, in the UK, area codes can be 5 digits - and UK websites never ask for a separate area code any more, it's completely pointless. Commented Nov 23, 2013 at 17:12
  • This is just the input format of the test program. I just want to know why the regex pattern returns an "empty iterator" or why val(cc,ac,n) = s doesn't work. A working solution would also help. Commented Nov 23, 2013 at 17:14

1 Answer 1

30

The problem is with your pattern. I would recommend using some tool like RegexPal to test them. Put the pattern in the first text box and your provided examples in the second one. It will highlight the matched parts.

You added spaces between your groups and [ -] separators, and it was expecting spaces there. The correct pattern is:

val pattern = """([0-9]{1,3})[ -]([0-9]{1,3})[ -]([0-9]{4,10})""".r

Also if you want to explicitly get groups then you want to get a Match returned. For an example the findFirstMatchIn function returns the first optional Match or the findAllMatchIn returns a list of matches:

val allMatches = pattern.findAllMatchIn(s)
allMatches.foreach { m =>
  println("CC=" + m.group(1) + "AC=" + m.group(2) + "Number=" + m.group(3))
}

val matched = pattern.findFirstMatchIn(s)
matched match {
  case Some(m) =>
    println("CC=" + m.group(1) + "AC=" + m.group(2) + "Number=" + m.group(3))
  case None =>
    println("There wasn't a match!")
}

I see you also tried extracting the string into variables. You have to use the Regex extractor in the following way:

val Pattern = """([0-9]{1,3})[ -]([0-9]{1,3})[ -]([0-9]{4,10})""".r
val Pattern(cc, ac, n) = s
println(s"CC=${cc}AC=${ac}Number=$n")

And if you want to handle errors:

s match {
  case Pattern(cc, ac, n) =>
    println(s"CC=${cc}AC=${ac}Number=$n")
  case _ =>
    println("No match!")
}

Also you can also take a look at string interpolation to make your strings easier to understand: s"..."

Sign up to request clarification or add additional context in comments.

2 Comments

I added spaces here to make it clearer, but apparently I made it more confusing. In my actual code, I did NOT put spaces before and after [ -] and it still didn't work.
If anyone is wondering why Pattern is uppercase, it's because as per the Scala style guide constants should be uppercase and this regex should be a constant.

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.