alphonse
alphonse

Reputation: 717

Swift How to get integer from string and convert it into integer

I need to extract numbers from string and put them into a new array in Swift.

var str = "I have to buy 3 apples, 7 bananas, 10eggs"

I tried to loop each characters and I have no idea to compare between Characters and Int.

Upvotes: 45

Views: 61075

Answers (10)

DàChún
DàChún

Reputation: 5156

Swift 5:

extension String {
var allNumbers: [Int] {
    let numbersInString = self.components(separatedBy: .decimalDigits.inverted).filter { !$0.isEmpty }
        return numbersInString.compactMap { Int($0) }
    }
}

You can get all numbers like

var str = "I have to buy 3 apples, 7 bananas, 10eggs"
// numbers = [3, 7, 10]
numbers = str.allNumbers

Upvotes: 2

George Maisuradze
George Maisuradze

Reputation: 2021

Swift 3/4

let string = "0kaksd020dk2kfj2123"
if let number = Int(string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()) {
    // Do something with this number
}

You can also make an extension like:

extension Int {
    static func parse(from string: String) -> Int? {
        Int(string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined())
    }
}

And then later use it like:

if let number = Int.parse(from: "0kaksd020dk2kfj2123") { 
    // Do something with this number
} 

Upvotes: 78

Pau Ballada
Pau Ballada

Reputation: 1628

For me makes more sense to have it as a String extension, probably it's a matter of tastes:

extension String {
 func parseToInt() -> Int? {
    return Int(self.components(separatedBy: CharacterSet.decimalDigits.inverted).joined())
 }
}

So can be used like this:

if let number = "0kaksd020dk2kfj2123".parseToInt() { 
// Do something with this number
} 

Upvotes: 7

Vasil Garov
Vasil Garov

Reputation: 4931

First, we split the string so we can process the single items. Then we use NSCharacterSet to select the numbers only.

import Foundation

let str = "I have to buy 3 apples, 7 bananas, 10eggs"
let strArr = str.split(separator: " ")

for item in strArr {
    let part = item.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()

    if let intVal = Int(part) {
        print("this is a number -> \(intVal)")
    }
}

Swift 4:

let string = "I have to buy 3 apples, 7 bananas, 10eggs"
let stringArray = string.components(separatedBy: CharacterSet.decimalDigits.inverted)
for item in stringArray {
    if let number = Int(item) {
        print("number: \(number)")
    }
}

Upvotes: 51

Alessandro Mattiuzzi
Alessandro Mattiuzzi

Reputation: 2467

Swift 2.2

  let strArr = str.characters.split{$0 == " "}.map(String.init)

        for item in strArr {
           let components = item.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)

                let part = components.joinWithSeparator("")

                    if let intVal = Int(part) {
                        print("this is a number -> \(intVal)")
                      }
              }

Upvotes: 2

steve0hh
steve0hh

Reputation: 637

Adapting from @flashadvanced's answer, I found that the following is shorter and simpler for me.

let str = "I have to buy 3 apples, 7 bananas, 10eggs"
let component = str.componentsSeparatedByCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet)
let list = component.filter({ $0 != "" }) // filter out all the empty strings in the component
print(list)

Tried in in the play ground and it works

Hope it helps :)

Upvotes: 6

Husein Kareem
Husein Kareem

Reputation: 526

let str = "Hello 1, World 62"
let intString = str.componentsSeparatedByCharactersInSet(
    NSCharacterSet
        .decimalDigitCharacterSet()
        .invertedSet)
    .joinWithSeparator("")

That will get you a string with all the number then you can just do this:

let int = Int(intString)

Just make sure you unwrap it since let int = Int(intString) is an optional.

Upvotes: 11

alphonse
alphonse

Reputation: 717

Thanks for everyone who answered to my question.

I was looking for a block of code which uses only swift grammar, because I'm learning grammar only now..

I got an answer for my question.Maybe it is not an easier way to solve, but it uses only swift language.

var article = "I have to buy 3 apples, 7 bananas, 10 eggs"
var charArray = Array(article)

var unitValue = 0
var total = 0
for char in charArray.reverse() {

    if let number = "\(char)".toInt() {
        if unitValue==0 {
            unitValue = 1
        }
        else {
            unitValue *= 10
        }
        total += number*unitValue
    }
    else {
        unitValue = 0
    }
}
println("I bought \(total) apples.")

Upvotes: 0

Martin R
Martin R

Reputation: 540075

Using the "regex helper function" from Swift extract regex matches:

func matchesForRegexInText(regex: String!, text: String!) -> [String] {

    let regex = NSRegularExpression(pattern: regex,
        options: nil, error: nil)!
    let nsString = text as NSString
    let results = regex.matchesInString(text,
        options: nil, range: NSMakeRange(0, nsString.length))
        as! [NSTextCheckingResult]
    return map(results) { nsString.substringWithRange($0.range)}
}

you can achieve that easily with

let str = "I have to buy 3 apples, 7 bananas, 10eggs"
let numbersAsStrings = matchesForRegexInText("\\d+", str) // [String]
let numbersAsInts = numbersAsStrings.map { $0.toInt()! }  // [Int]

println(numbersAsInts) // [3, 7, 10]

The pattern "\d+" matches one or more decimal digit.


Of course the same can be done without the use of a helper function if you prefer that for whatever reason:

let str = "I have to buy 3 apples, 7 bananas, 10eggs"
let regex = NSRegularExpression(pattern: "\\d+", options: nil, error: nil)!
let nsString = str as NSString
let results = regex.matchesInString(str, options: nil, range: NSMakeRange(0, nsString.length))
    as! [NSTextCheckingResult]
let numbers = map(results) { nsString.substringWithRange($0.range).toInt()! }
println(numbers) // [3, 7, 10]

Alternative solution without regular expressions:

let str = "I have to buy 3 apples, 7 bananas, 10eggs"

let digits = "0123456789"
let numbers = split(str, allowEmptySlices: false) { !contains(digits, $0) }
    .map { $0.toInt()! }
println(numbers) // [3, 7, 10]

Upvotes: 11

milo526
milo526

Reputation: 5083

// This will only work with single digit numbers. Works with “10eggs” (no space between number and word
var str = "I have to buy 3 apples, 7 bananas, 10eggs"
var ints: [Int] = []
for char:Character in str {
  if let int = "\(char)".toInt(){
    ints.append(int)
  }
}

The trick here is that you can check if a string is an integer (but you can’t check if a character is). By looping though every character of the string, use string interpolation to create a string from the character and check if that string cas be casted as a integer.
If it can be, add it to the array.

// This will work with multi digit numbers. Does NOT work with “10 eggs” (has to have a space between number and word)
var str = "I have to buy 3 apples, 7 bananas, 10 eggs"
var ints: [Int] = []
var strArray = split(str) {$0 == " "}
for subString in strArray{
  if let int = subString.toInt(){
    ints.append(int)
  }
}

Here we split the string at any space and create an array of every substring that is in the long string.
We again check every string to see if it is (or can be casted as) an integer.

Upvotes: 1

Related Questions