57

I need to determine if a string contains any of the characters from a custom set that I have defined.

I see from this post that you can use rangeOfString to determine if a string contains another string. This, of course, also works for characters if you test each character one at a time.

I'm wondering what the best way to do this is.

Community
  • 1
  • 1
mattnedrich
  • 7,577
  • 9
  • 39
  • 45

11 Answers11

97

You can create a CharacterSet containing the set of your custom characters and then test the membership against this character set:

Swift 3:

let charset = CharacterSet(charactersIn: "aw")
if str.rangeOfCharacter(from: charset) != nil {
    print("yes")
}

For case-insensitive comparison, use

if str.lowercased().rangeOfCharacter(from: charset) != nil {
    print("yes")
}

(assuming that the character set contains only lowercase letters).

Swift 2:

let charset = NSCharacterSet(charactersInString: "aw")
if str.rangeOfCharacterFromSet(charset) != nil {
    print("yes")
}

Swift 1.2

let charset = NSCharacterSet(charactersInString: "aw")
if str.rangeOfCharacterFromSet(charset, options: nil, range: nil) != nil {
    println("yes")
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Why lowercase? It could be that the custom character set specifically excludes some or all lowercase characters. Also, CharacterSet conforms to the SetAlgebra protocol; CharacterSet.isDisjoint() could be used to determine if the custom CharacterSet has any members in common with the input string (as per Chris Hatton's answer below, but with CharacterSets instead of Sets.) – Matt Mar 04 '17 at 05:21
  • @Matt: I do not remember why I added the lowercase conversion, perhaps as an option or because it is used in the Q&A which is referenced in the question. I have tried to clarify that now. – And yes, you could write `if !charset.isDisjoint(with: CharacterSet(charactersIn: str))`. Is that what you meant? Not sure if it is simpler or more efficient. – Martin R Mar 04 '17 at 09:04
  • @MartinR Do you know why `rangeOfCharacter(from: charset, options: .caseInsensitive)` doesn't work? – Leo Dabus Jan 15 '18 at 15:05
  • 2
    @LeoDabus: https://developer.apple.com/documentation/foundation/nsstring/1416898-rangeofcharacter specifies "anchored" and "backwards" as the only possible options. The technical reason might be that a CharacterSet is internally just a large bitmap (for efficiency). – Martin R Jan 15 '18 at 15:14
23

ONE LINE Swift4 solution to check if contains letters:

CharacterSet.letters.isSuperset(of: CharacterSet(charactersIn: myString) // returns BOOL

Another case when you need to validate string for custom char sets. For example if string contains only letters and (for example) dashes and spaces:

let customSet: CharacterSet = [" ", "-"]
let finalSet = CharacterSet.letters.union(customSet)
finalSet.isSuperset(of: CharacterSet(charactersIn: myString)) // BOOL

Hope it helps someone one day:)

Tung Fam
  • 7,899
  • 4
  • 56
  • 63
9

Swift 3 example:

extension String{
    var isContainsLetters : Bool{
        let letters = CharacterSet.letters
        return self.rangeOfCharacter(from: letters) != nil
    }
}

Usage :

"123".isContainsLetters // false
Maor
  • 3,340
  • 3
  • 29
  • 38
7

From Swift 1.2 you can do that using Set

var str = "Hello, World!"
let charset: Set<Character> = ["e", "n"]

charset.isSubsetOf(str)     // `true` if `str` contains all characters in `charset`
charset.isDisjointWith(str) // `true` if `str` does not contains any characters in `charset`
charset.intersect(str)      // set of characters both `str` and `charset` contains.

Swift 3 or later

let isSubset = charset.isSubset(of: str)        // `true` if `str` contains all characters in `charset`
let isDisjoint = charset.isDisjoint(with: str)  // `true` if `str` does not contains any characters in `charset`
let intersection = charset.intersection(str)    // set of characters both `str` and `charset` contains.
print(intersection.count)   // 1
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
rintaro
  • 51,423
  • 14
  • 131
  • 139
4

swift3

var str = "Hello, playground"
let res = str.characters.contains { ["x", "z"].contains( $0 ) }
t4ncr3d3
  • 615
  • 1
  • 8
  • 17
3

Using Swift 3 to determine if your string contains characters from a specific CharacterSet:

    let letters = CharacterSet.alphanumerics
    let string = "my-string_"
    if (string.trimmingCharacters(in: letters) != "") {
        print("Invalid characters in string.")
    }
    else {
        print("Only letters and numbers.")
    }
AndyDunn
  • 1,074
  • 1
  • 12
  • 19
  • 2
    For a real Swift 3 answer, you should use `CharacterSet` instead of `NSCharacterSet`. – Eric Aya Nov 21 '16 at 15:40
  • 1
    This isn't going to test whether the string "contains" the characters in the set. It only tests whether the ends of the string have characters in that set. Internal characters are ignored. – SmileBot Nov 29 '18 at 14:38
2
func isAnyCharacter( from charSetString: String, containedIn string: String ) -> Bool
{
    return Set( charSetString.characters ).isDisjointWith( Set( string.characters) ) == false
}
Chris Hatton
  • 787
  • 9
  • 17
1

Swift 4

let myString = "Some Words"

if myString.contains("Some"){
    print("myString contains the word `Some`")
}else{
    print("myString does NOT contain the word `Some`")
}

Swift 3:

let myString = "Some Words"

if (myString.range(of: "Some") != nil){
    print("myString contains the word `Some`")
}else{
    print("Word does not contain `Some`")
}
fs_tigre
  • 10,650
  • 13
  • 73
  • 146
1

Updated for Swift 5.1

Question was specifically: "if a string contains any of the characters from a custom set" and not checking for all characters in the custom set.

Using

func check(in string: String, forAnyIn characters: String) -> Bool {
    // create one character set
    let customSet = CharacterSet(charactersIn: characters)
    // use the rangeOfCharacter(from: CharacterSet) function
    return string.rangeOfCharacter(from: customSet) != nil 
}

check(in: "abc", forAnyIn: "A") // false
check(in: "abc", forAnyIn: "b") // true

But this is also very easy to check using character sets.


func check(in string: String, forAnyIn characters: String) -> Bool {
    let customSet = CharacterSet(charactersIn: characters)
    let inputSet = CharacterSet(charactersIn: string)
    return !inputSet.intersection(customSet).isEmpty
}

check(in: "abc", forAnyIn: "A") // false
check(in: "abc", forAnyIn: "b") // true

multitudes
  • 2,898
  • 2
  • 22
  • 29
0

You could do it this way:

var string = "Hello, World!"

if string.rangeOfString("W") != nil {
     println("exists")
} else {
     println("doesn't exist")
}

// alternative: not case sensitive
if string.lowercaseString.rangeOfString("w") != nil {
     println("exists")
} else {
     println("doesn't exist")
}
Cesare
  • 9,139
  • 16
  • 78
  • 130
-1

Use like this in swift 4.2

    var string = "Hello, World!"
    let charSet = NSCharacterSet.letters
    if string.rangeOfCharacter(from:charSet)?.isEmpty == false{  
      print ("String contain letters");
    }