Swift filter array of strings

后端 未结 4 1976
日久生厌
日久生厌 2021-02-20 15:49

I\'ve had troubles filtering array of keywords (strings) in swift ,My code:

self.filteredKeywords=filter(keywords.allValues, {(keyword:NSString) ->                    


        
相关标签:
4条回答
  • 2021-02-20 16:07

    [Updated for Swift 2.0]

    As NSString is toll-free bridged to Swift String, just avoid the coercions with:

      3> ["abc", "bcd", "xyz"].filter() { nil != $0.rangeOfString("bc") }
    $R1: [String] = 2 values {
      [0] = "abc"
      [1] = "bcd"
    }
    

    But, if you think allValues aren't strings:

    (keywords.allValues as? [String]).filter() { nil != $0.rangeOfString("bc") }
    

    which returns an optional array.

    0 讨论(0)
  • 2021-02-20 16:16

    Swift 4.2 provides a new way to do this:

    var theBigLebowski = ["The Dude", "Angry Walter", "Maude Lebowski", "Donny Kerabatsos", "The Big Lebowski", "Little Larry Sellers"]
    
    // after removeAll -> ["The Dude", "Angry Walter", "Donny Kerabatsos", "Little Larry Sellers"]
    theBigLebowski.removeAll{ $0.contains("Lebowski")}
    print(theBigLebowski)
    
    0 讨论(0)
  • 2021-02-20 16:26

    Your filter is over [AnyObject], but your closure takes NSString. These need to match. Also, your result needs to be a Bool, not a Bool?. You can address these simply like this:

    self.filteredKeywords = filter(keywords.allValues, {
        let keyword = $0 as? NSString
        return keyword?.containsString(searchText) ?? false
    })
    

    This accepts AnyObject and then tries to coerce it down to NSString. It then nil-coalleces (??) the result to make sure it always is a Bool.

    I'd recommend, though, treating keywords as a [String:String] rather than an NSDictionary. That would get rid of all the complications of AnyObject. Then you can just do this:

    self.filteredKeywords = keywords.values.filter { $0.rangeOfString(searchText) != nil }
    

    Whenever possible, convert Foundation collections into Swift collections as soon as you can and store those. If you have incoming Foundation objects, you can generally convert them easily with techniques like:

    let dict = nsdict as? [String:String] ?? [:]
    

    Or you can do the following to convert them such that they'll crash in debug (but silently "work" in release):

    func failWith<T>(msg: String, value: T) -> T {
        assertionFailure(msg)
        return value
    }
    
    let dict = nsdict as? [String:String] ?? failWith("Couldn't convert \(d)", [:])
    
    0 讨论(0)
  • 2021-02-20 16:31

    There is both a problem with GoZoner's answer for certain data types and also a slightly better way to do this. The following examples can show this:

    let animalArray: NSMutableArray = ["Dog","Cat","Otter","Deer","Rabbit"]
    let filteredAnimals = animalArray.filter { $0.rangeOfString("er") != nil }
    print("filteredAnimals:", filteredAnimals)
    
    filteredAnimals: [Dog, Cat, Otter, Deer, Rabbit]
    

    Likely not the set you expected!

    However this works fine this way if we don't type animalArray as an NSMutableArray:

    let animalArray = ["Dog","Cat","Otter","Deer","Rabbit"]
    let filteredAnimals = animalArray.filter { $0.rangeOfString("er") != nil }
    print("filteredAnimals:", filteredAnimals)
    
    filteredAnimals: [Otter, Deer]
    

    However I'd recommend using $0.contains() instead of $0.rangeOfString() != nil because it functions in both circumstances and slightly enhances the readability of the code:

    let animalArray: NSMutableArray = ["Dog","Cat","Otter","Deer","Rabbit"]
    let filteredAnimals = animalArray.filter { $0.contains("er") }
    print("filteredAnimals:", filteredAnimals)
    
    filteredAnimals: [Otter, Deer]
    
    0 讨论(0)
提交回复
热议问题