user3043098 - 1 year ago 72
Swift Question

# Check and get only Int's out of an Array of Strings

Im currently working on a small app for chemical calculations. Im trying to program a Mol Calculator in which you just have to enter the sum formula and the amount of it. Without any numbers it works perfectly, for example if i enter

`NaCl`
with an amount of
`100`
grams (you enter the gram in a different text field) you get about 1.73 mol, which is the correct solution.

What i want to do now is that i can add numbers, for example
`Na2Cl4`
. In my method, the string is splitted up properly, if you print it you get
`["Na", "2", "Cl", "4"]`
but i don't know how i can get the Int's out and remember to which element they were assigned to (2 to Na and 4 to Cl, because i need to multiply the mol/g with the 2).

I tried the following:
The number will always be on a odd index (Na at 0, 2 at 1, Cl at 2, 4 at 3), so i tried to put every element at a odd index into a new array :

``````var i = 0
var testarray = [String]()

for content in splitted {
if i % 2 == 0 {

}else {
testarray.append(content)
}
print(content)
i += 1
}
``````

splitted is the [String] array which contains the splitted sum formula. The result i get if i print out content is 2 and 4 which is fine but if i enter for example Na10 i get 1 and 0 which is not good, also it does not know to which element it was assigned to.

Does anybody know how to solve this problem that i can get the Int values out of the string array and remember to which element they were assigned to ?

EDIT:

Heres the code how i split the string:

``````let splitted = summenformel.characters.splitBefore(separator: { \$0.isUpperCase }).map{String(\$0)}
``````

and the extensions:

``````    extension Sequence {
func splitBefore(
separator isSeparator: (Iterator.Element) throws -> Bool
) rethrows -> [AnySequence<Iterator.Element>] {
var result: [AnySequence<Iterator.Element>] = []
var subSequence: [Iterator.Element] = []

var iterator = self.makeIterator()
while let element = iterator.next() {
if try isSeparator(element) {
if !subSequence.isEmpty {
result.append(AnySequence(subSequence))
}
subSequence = [element]
}
else {
subSequence.append(element)
}
}
result.append(AnySequence(subSequence))
return result
}
}

extension Character {
var isUpperCase: Bool { return String(self) == String(self).uppercased() }
}
``````

Alternative approach with regular expression

The regex searches for:

a capital letter followed by optional lowercase letters followed by optional numbers.

``````let string = "Na10Cl4"

let pattern = "([A-Z]([a-z]+)?)(\\d+)?"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
let matches = regex.matches(in: string, options: [], range: NSRange(location: 0, length: string.characters.count))
for match in matches {
let elementRange = match.rangeAt(1)
let element = (string as NSString).substring(with: elementRange)
print("element", element)
let quantityRange = match.rangeAt(3)
let quantity : Int
if quantityRange.location != NSNotFound {
quantity = Int((string as NSString).substring(with: quantityRange))!
} else {
quantity = 1
}
print("quantity", quantity)
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download