45

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.

2
  • check this post for how to convert a string item to int stackoverflow.com/questions/24115141/… Commented May 20, 2015 at 7:15
  • let a:Int? = str.toInt() gives me a nil value.. Commented May 20, 2015 at 7:24

10 Answers 10

78

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
} 
Sign up to request clarification or add additional context in comments.

1 Comment

This doesn't answer the question. The question wants to extract all numbers from a string into an array. This code returns a single Int made up of all digits found in the string.
52

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)")
    }
}

2 Comments

It's the easier and the better way to achive what you looking for. For simplify and look easy to use in your app, you can't create a extension of String class and create a method named extractNumbers
In Swift 2, split does not longer works on Strings. see stackoverflow.com/a/30759312/2959462
11

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]

1 Comment

thanks for an answer, bur I'm looking for not using function.but Thank you very much.
11
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.

1 Comment

This doesn't answer the question. The question wants to extract all numbers from a string into an array. This code returns a single Int made up of all digits found in the string.
8

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
} 

1 Comment

This doesn't answer the question. The question wants to extract all numbers from a string into an array. This code returns a single Int made up of all digits found in the string. This is also a duplicate of a previous answer.
6

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 :)

2 Comments

This will return array of decimals with string type.Nice work.
let component = str.components(separatedBy: NSCharacterSet.decimalDigits.inverted) -> Swift 5
2

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)")
                      }
              }

Comments

2

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

Comments

1
// 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.

4 Comments

thanks a lot! but it recognizes 10 like 1 and 0 .how can i get number 10?
Is there always a space between an integer and anything else?
Is it possible to check, if after a number goes a number again (without space) , it recognizes as a one number??
It is but it really isn’t gonna be any easier or prettier than @flashadvanced answer (and you should probably mark his answer as “the” answer)
0

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.")

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.