Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 1.2 Filter an Array of Structs by keyword

Tags:

arrays

swift

I need some help filtering an array of Structs.

This is what I am doing currently, it filters the array but not correctly. For example lets say I search for an item in the array with "Mid" I have one item that should be shown however the item shown starts with "Bad".

    var array = breweries.filter() { $0.name?.lowercaseString.rangeOfString(searchController.searchBar.text.lowercaseString) != nil }

    results = array

here is my Struct

struct Breweries {
    let name: String?
    let breweryId: String?
    let distance: Double?
    let largeIconURL: String?
    let streetAddress: String?
    let locality: String?
    let region: String?
    let phone: String?
    let website: String?

    init(brewDictionary: [String: AnyObject]) {

        name = brewDictionary["brewery"]?["name"] as? String
        breweryId = brewDictionary["breweryId"] as? String
        distance = brewDictionary["distance"] as? Double
        largeIconURL = brewDictionary["brewery"]?["images"]??.objectForKey("large") as? String
        streetAddress = brewDictionary["streetAddress"] as? String
        locality = brewDictionary["locality"] as? String
        region = brewDictionary["region"] as? String
        phone = brewDictionary["phone"] as? String
        website = brewDictionary["website"] as? String


    }
}

Please point in the right direction!

Note: I am using Swift 1.2

Update:

I thought a video would be of help to better explain what I am trying to do.

Demo Of issue

What I want is to find the filter the array so only the item with a similar name is shown.

Update 2: As it turns out I forgot to handle the case when my UISearchController was active.

like image 549
MillerApps Avatar asked Jul 22 '15 18:07

MillerApps


2 Answers

Assuming your Struct name is Breweries and it has a name property, try this:

let array = breweries.filter() {
    ($0.name!.lowercaseString as NSString).containsString(searchController.searchBar.text.lowercaseString)
}
like image 161
Profezy Avatar answered Nov 03 '22 18:11

Profezy


Your usage of filter is correct, but your closure seem to be complicated with no clear goal. I suggest you to write an extension (or possibly use what I am using):

extension String {

    func contains(search: String, ignoreCase: Bool = false, ignoreDiacritic: Bool = false) -> Bool {

        var options = NSStringCompareOptions.allZeros

        if ignoreCase { options |= NSStringCompareOptions.CaseInsensitiveSearch }
        if ignoreDiacritic { options |= NSStringCompareOptions.DiacriticInsensitiveSearch }

        return self.rangeOfString(search, options: options) != nil
     }
}

This way you can use closure like this to search:

breweries.filter() { 
    $0.name?.contains("x") // Precise search
    $0.name?.contains("x", ignoreCase: true, ignoreDiacritics: true) // Ignores diacritics and lower / upper case
}

of course, you can use | or & to search for multiple parameters

breweries.filter() { 
    $0.name?.contains("x") || $0.streetAddress?.contains("x")
}

Hope it helps!

like image 20
Jiri Trecak Avatar answered Nov 03 '22 18:11

Jiri Trecak