Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift filter array of strings

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

self.filteredKeywords=filter(keywords.allValues, {(keyword:NSString) ->                                              
  Bool in
    let words=keyword as? NSString
    return words?.containsString(searchText)
  })

As AnyObject can't be subtype of NSString, I'm stuck with this!

like image 473
Meseery Avatar asked Apr 04 '15 15:04

Meseery


2 Answers

[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.

like image 77
GoZoner Avatar answered Oct 17 '22 15:10

GoZoner


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)", [:])
like image 41
Rob Napier Avatar answered Oct 17 '22 14:10

Rob Napier