73

I have an array ["abc", "94761178","790"]

I want to iterate each and check is a String or an Int?

How to check it?

How to convert "123" to integer 123?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
user3675188
  • 7,271
  • 11
  • 40
  • 76

17 Answers17

74

Here is a small Swift version using String extension :

Swift 3/Swift 4 :

extension String  {
    var isNumber: Bool {
        return !isEmpty && rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
    }
}

Swift 2 :

   extension String  {
        var isNumber : Bool {
            get{
                return !self.isEmpty && self.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet) == nil
            }
        }
   }
Pramodya Abeysinghe
  • 1,098
  • 17
  • 13
CryingHippo
  • 5,026
  • 1
  • 28
  • 32
61

Edit Swift 2.2:

In swift 2.2 use Int(yourArray[1])

var yourArray = ["abc", "94761178","790"]
var num = Int(yourArray[1])
if num != nil {
 println("Valid Integer")
}
else {
 println("Not Valid Integer")
}

It will show you that string is valid integer and num contains valid Int.You can do your calculation with num.

From docs:

If the string represents an integer that fits into an Int, returns the corresponding integer.This accepts strings that match the regular expression "[-+]?[0-9]+" only.

codester
  • 36,891
  • 10
  • 74
  • 72
  • 13
    Be warned that this only works up to 2^31 - 1 (signed integer limit on 32-bit arch). I saw this in a project I'm working on related to phone numbers, and phone numbers can easily surpass that limit. – Can Nov 25 '15 at 22:27
  • 1
    This code causes a compile error in Swift 2.2. "toInt() is no longer available: use Int() initializer" – mbonness Apr 22 '16 at 04:22
  • @Can good point, this tripped me up too. I added an answer that handles numbers of any size, including 10 or 11 digit phone numbers. – Kyle Clegg Jun 30 '16 at 18:41
  • That's kind of funny; I still think of phone numbers as alpha characters. It wasn't *that* long ago that something like 215-LU6-5858 was a perfectly valid way to represent a phone number. :) I still *mostly* treat them as alpha-numerics in databases, however I'm retraining myself to change that with phone number parsers and dialer code. I do continue to giggle when I see USA-only programmers putting zip codes in number fields. #wisdomofage ;) – ChrisH Mar 07 '18 at 14:37
47

Be aware that checking a string/number using the Int initializer has limits. Specifically, a max value of 2^32-1 or 4294967295. This can lead to problems, as a phone number of 8005551234 will fail the Int(8005551234) check despite being a valid number.

A much safer approach is to use NSCharacterSet to check for any characters matching the decimal set in the range of the string.

let number = "8005551234"
let numberCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
if !number.isEmpty && number.rangeOfCharacterFromSet(numberCharacters) == nil {
    // string is a valid number
} else {
    // string contained non-digit characters
}

Additionally, it could be useful to add this to a String extension.

public extension String {

    func isNumber() -> Bool {
        let numberCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet
        return !self.isEmpty && self.rangeOfCharacterFromSet(numberCharacters) == nil
    }

}
ZadrackSaria
  • 103
  • 6
Kyle Clegg
  • 38,547
  • 26
  • 130
  • 141
  • If the string is empty it will still return true. po "".rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet) nil – CryingHippo Jul 20 '16 at 12:21
  • @CryingHippo try adding a `!number.isEmpty` check – Kyle Clegg Jul 20 '16 at 17:14
  • 3
    What's the point of adding `.invertedSet` instead of changing the return to `!= nil`? Is it better runtime or something? – Tommy K Feb 11 '17 at 17:57
  • 2
    @TommyK if you check for non-inverted set, then you see if String contains numbers, but you don't know if it's digits only. – Dmitry Zhukov May 01 '17 at 12:21
  • this is now `if !text_of_just_numbers.isEmpty && text_of_just_numbers.isEmpty.rangeOfCharacter(from: NSCharacterSet.decimalDigits.inverted) == nil { //is numeric }` in Swift 4.2 – Mr Heelis Mar 21 '19 at 16:06
31

I think the nicest solution is:

extension String {
    var isNumeric : Bool {
        return Double(self) != nil
    }
}
Bence Pattogato
  • 3,752
  • 22
  • 30
21

Starting from Swift 2, String.toInt() was removed. A new Int Initializer was being introduced: Int(str: String)

for target in ["abc", "94761178","790"]
{
  if let number = Int(target)
  {
     print("value: \(target) is a valid number. add one to get :\(number+1)!")
  }
  else
  {
    print("value: \(target) is not a valid  number.")
  }
}
AMTourky
  • 1,190
  • 13
  • 25
9

Swift 3, 4

extension String {
    var isNumber: Bool {
        let characters = CharacterSet.decimalDigits.inverted
        return !self.isEmpty && rangeOfCharacter(from: characters) == nil
    }
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Said Sikira
  • 4,482
  • 29
  • 42
8

Simple solution like this:

extension String {
    public var isNumber: Bool {
        return !isEmpty && rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
    }
}
Harry Zhang
  • 799
  • 9
  • 6
6

I think using NumberFormatter is an easy way: (Swift 5)

import Foundation

extension String {

    private static let numberFormatter = NumberFormatter()

    var isNumeric : Bool {
        Self.numberFormatter.number(from: self) != nil
    }
}

Amir Khorsandi
  • 3,542
  • 1
  • 34
  • 38
4

The correct way is to use the toInt() method of String, and an optional binding to determine whether the conversion succeeded or not. So your loop would look like:

let myArray = ["abc", "94761178","790"]

for val in myArray {
    if let intValue = val.toInt() {
        // It's an int
        println(intValue)
    } else {
        // It's not an int
        println(val)
    }
}

The toInt() method returns an Int?, so an optional Int, which is nil if the string cannot be converted ton an integer, or an Int value (wrapped in the optional) if the conversion succeeds.

The method documentation (shown using CMD+click on toInt in Xcode) says:

If the string represents an integer that fits into an Int, returns the corresponding integer. This accepts strings that match the regular expression "[-+]?[0-9]+" only.

Antonio
  • 71,651
  • 11
  • 148
  • 165
4

This way works also with strings with mixed numbers:

public extension String {
func isNumber() -> Bool {
    return !self.isEmpty && self.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil && self.rangeOfCharacter(from: CharacterSet.letters) == nil
}}

So u get something like this: enter image description here

Boris
  • 178
  • 1
  • 7
1

Swift 3.0 version

func isNumber(stringToTest : String) -> Bool {
    let numberCharacters = CharacterSet.decimalDigits.inverted
    return !s.isEmpty && s.rangeOfCharacter(from:numberCharacters) == nil
}
Mohamed.A.A
  • 344
  • 3
  • 5
0

If you want to accept a more fine-grained approach (i.e. accept a number like 4.5 or 3e10), you proceed like this:

func isNumber(val: String) -> Bool
{
   var result: Bool = false
   let parseDotComNumberCharacterSet = NSMutableCharacterSet.decimalDigitCharacterSet()
   parseDotComNumberCharacterSet.formUnionWithCharacterSet(NSCharacterSet(charactersInString: ".e"))

            let noNumberCharacters = parseDotComNumberCharacterSet.invertedSet
            if let v = val
            {
                result = !v.isEmpty && v.rangeOfCharacterFromSet(noNumberCharacters) == nil
            }
   return result
}

For even better resolution, you might draw on regular expression..

YakovL
  • 7,557
  • 12
  • 62
  • 102
0

Xcode 8 and Swift 3.0

We can also check :

 //MARK: - NUMERIC DIGITS
        class func isString10Digits(ten_digits: String) -> Bool{

            if !ten_digits.isEmpty {

                let numberCharacters = NSCharacterSet.decimalDigits.inverted
                return !ten_digits.isEmpty && ten_digits.rangeOfCharacter(from: numberCharacters) == nil 
            }
            return false
        }
Anil Gupta
  • 1,155
  • 1
  • 19
  • 26
0

This code works for me for Swift 3/4

  func isNumber(textField: UITextField) -> Bool {
    let allowedCharacters = CharacterSet.decimalDigits
    let characterSet = CharacterSet(charactersIn: textField.text!)
    return allowedCharacters.isSuperset(of: characterSet)
  //        return true 
  }
Thiru P
  • 11
  • 3
0

You can use this for integers of any length.

func getIntegerStrings(from givenStrings: [String]) -> [String]
{
    var integerStrings = [String]()
    for string in givenStrings
    {
        let isValidInteger = isInteger(givenString: string)
        if isValidInteger { integerStrings.append(string) }
    }
    return integerStrings
}

func isInteger(givenString: String) -> Bool
{
    var answer = true
    givenString.forEach { answer = ("0"..."9").contains($0) && answer }
    return answer
}

func getIntegers(from integerStrings: [String]) -> [Int]
{
    let integers = integerStrings.compactMap { Int($0) }
    return integers
}

let strings = ["abc", "94761178", "790", "18446744073709551615000000"]
let integerStrings = getIntegerStrings(from: strings)
let integers = getIntegers(from: integerStrings)

print(integerStrings) // ["94761178", "790", "18446744073709551615000000"]
print(integers) // [94761178, 790]

However, as pointed out by @Can, you can get the integer value for the number only up to 2^31 - 1 (signed integer limit on 32-bit arch). For the larger value, however, you will still get the string representation.

Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
0

This code will return an array of converted integers:


["abc", "94761178","790"].map(Int.init) // returns [ nil, 94761178, 790 ]

OR

["abc", "94761178","790"].map { Int($0) ?? 0 } // returns [ 0, 94761178, 790 ]
Alchi
  • 799
  • 9
  • 19
-6

Get the following isInteger() function from the below stackoverflow post posted by corsiKa: Determine if a String is an Integer in Java

And I think this is what you want to do (where nameOfArray is the array you want to pass)

void convertStrArrayToIntArray( int[] integerArray ) {

    for (int i = 0; i < nameOfArray.length(); i++) {
        if (!isInteger(nameOfArray[i])) {
            integerArray[i] = nameOfArray[i].toString();
        }
    }

}
Community
  • 1
  • 1
Ian Fell
  • 7
  • 3