0

I'm working on a Speech Recogniser module in my app. Speech recognizer returns a string (maybe some time with garbage string information, closely matching with user's speech) and I have to evaluate specific command from a string.

Here are some speech result string examples, that I'm getting:

  • "open case"
  • "open case 1234"
  • "open case id 3421"
  • "open case no 9546"
  • "open case number 5241"
  • "open case 9552 open case"
  • "open case open case 6842"
  • "open case bla bla 5415 bla"
  • "open case 1234 bla bla"
  • "open case number 54675 bla bla 1234 bla" . // first integer should be considered in command

Now, I've a set of command list, one of command is open case <Integer value>

I could easily evaluate the word open case using substring utility functions of Swift. But the problem is, I've to find out (identify and get) an integer number from a speech string after keyword open case.

I've looked around the following answer but couldn't find the exact result/solution:

Udara Abeythilake
  • 1,215
  • 1
  • 20
  • 31
Krunal
  • 77,632
  • 48
  • 245
  • 261

3 Answers3

6

I recommend Regular Expression.

The pattern searches for

  • Literal "open case",
  • An optional whitespace character (\\s?)
  • One or more digits. (\\d+) which is captured

The code evaluates all examples:

let array = ["open case", "open case 1234", "open case id 3421", "open case no 9546", "open case number 5241", "open case 9552 open case", "open case open case 6842", "open case bla bla 5415 bla", "open case 1234 bla bla", "open case number 54675 bla bla bla"]

func evaluate(string : String) -> String? {
    let pattern = "open case\\s?(\\d+)"
    let regex = try! NSRegularExpression(pattern: pattern) // as the pattern is hard-coded try! is safe
    if let match = regex.firstMatch(in: string, range: NSRange(string.startIndex..., in: string)) {
        let range = Range(match.range(at: 1), in: string)!
        return String(string[range])
    }
    return nil
}

let found = array.compactMap { evaluate(string: $0) } // ["1234", "9552", "6842", "1234"]

If you want to consider (actually ignore) everything between open case and the integer use the pattern

"open case\\D+(\\d+)"

\\D+ represents one or more non-digit characters.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • Need you help one more time to find out a accurate regex pattern, matching with this string **open bla case bla 62 72 769 bla bla**. I've tried this one `open\\D+case\\D+(\\d+)\\s*(\\d+)\\s*(\\d+)` but it fails if there are more than 3 matches for combination of `space + number`. – Krunal May 14 '18 at 18:18
  • Try `"open\\D+case\\D+([\\d ]+\\d)"`, the numeric search considers digits and spaces with a trailing digit. – vadian May 14 '18 at 18:34
  • Thank you.. You are great! Why couldn't I thought it? – Krunal May 14 '18 at 18:37
  • 1
    If you also want to consider only a single digit you have to replace the `+` after the closing bracket (one or more) with `*` (zero or more) – vadian May 14 '18 at 18:46
5

You can use something like:

let string = "open case 9552 open case"

if let number = string.components(separatedBy: .whitespaces).compactMap(Int.init).first {
    print(number)
}

If you're using Swift 4.0 or below use flatMap instead of compactMap.

Mukesh
  • 2,792
  • 15
  • 32
5

I like regex.

let input = "open case 1234 bla bla"
let pattern = "open case ([0-9]+)"
do {
    let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
    let matches = regex.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count))
    if matches.count > 0 {
        let match = matches[0]
        let r = match.range(at: 1)
        let num = input.substring(with: Range(r, in: input)!)
        // "1234"
    }
} catch {
    print("illegal regex")
}
matt
  • 515,959
  • 87
  • 875
  • 1,141