-1

I've got a problem: I'm trying to determine how many Ints and Doubles a string has, for example:

12.5+45-(67.78)*3

Expected Results:

2 Ints: 45, 3

2 Doubles: 12.5, 67.78

7 symbols: .,+,-,(,.,),*

How do I determine this?
Thanks in advance. I'm totally new to Swift

LinusGeffarth
  • 27,197
  • 29
  • 120
  • 174

3 Answers3

1

NSRegularExpression can search for everything in string. This is an example to get number from string:

Swift extract regex matches

You can use this regex string to get Float number: "\d+\.\d+" or this to get Int number: "\\d+"

Community
  • 1
  • 1
Luan Lai
  • 473
  • 2
  • 10
1
let math = "+-/*()"
let teststring = "10+12.44/(3.14*7+20)"

let isOperator = { c in
    math.characters.contains(c)
}


let numbers = teststring.characters.split(whereSeparator: isOperator).map(String.init)
let operators = teststring.characters.filter(isOperator)

let integers = numbers.flatMap { Int($0) }
let doubles = numbers.flatMap { c->Double? in
    if let i = Int(c) {
        return nil
    } else {
        return Double(c)
    }
}

print("\(operators.count) operators \(operators)")
print("\(integers.count) integers \(integers)")
print("\(doubles.count) doubles \(doubles)")

/* prints

 6 operators ["+", "/", "(", "*", "+", ")"]
 3 integers [10, 7, 20]
 2 doubles [12.44, 3.1400000000000001]

 */
user3441734
  • 16,722
  • 2
  • 40
  • 59
0

I would suggest decomposing the formula in substring and placing the information in an array that allows you to access individual components.

It will be easier to count operators, integers, numbers, etc. once you have that first level of parsing done.

Here's an example of how you could produce the parsed array:

let formula = "10+12.44/(3.14*7+20)"

let operators = "+-*/()"
let operSet   = Set(operators.characters)


let flags   = formula.characters.indices
              .map{($0,operSet.contains(formula[$0]))}
              // [(String.Index,Bool)]

let starts  = zip(flags,  [(formula.startIndex,true)] + flags)
              .filter{ $0.1 || $1.1 }.map{$0.0.0}
              // [String.Index]

let parsed  = zip(starts, starts.dropFirst() + [formula.endIndex])
              .map{ (string:formula[$0..<$1], start:$0, end:$1) }
              // [(String, String.Index, String.Index)]

// parsed will contain tupples with substrings and start/end indexes
//
// .string    .start   .end
// -------    ------   ----
//   10          0       2
//   +           2       3
//   12.44       3       8
//   /           8       9
//   (           9      10
//   3.14       10      14
//   *          14      15
//   7          15      16
//   +          16      17
//   20         17      19
//   )          19      20

You can then use this array for your various needs and, as a bonus you have the .start and .end to get to each of the fomula substrings

let operators = parsed.filter{operators.contains($0.string)} 

let integers = parsed.filter{Int($0.string) != nil}

let decimals = parsed.filter{$0.string.contains(".")}

The way it works is by first flagging all the string indexes that correspond to an operator (the flags variable).

The formula substrings will start on each operator and on any character that follows an operator (the starts variable).

Once we have all the string indexes for the starting positions of the formula substrings, we only need to convert them to ranges (i.e. from each start to the next one) and extract the substrings into an array.

I could have just placed the substrings in the array but since you'll need the positions in the formula string, I made it a tuple with the index range as well (the parsed variable).

Once you have the parsed array, counting operators, integers etc. becomes a simple matter of filtering.

Note that this will only work for single character operators.

Alain T.
  • 40,517
  • 4
  • 31
  • 51