简体   繁体   中英

Swift 1.2 Filter an Array of Structs by keyword

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.

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)
}

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!

Here is an example from an investing app with struct:

import Foundation

public struct SNStock {

  public let ticker:NSString
  public let name:NSString

  init(ticker:NSString, name:NSString) {
    self.ticker = ticker
    self.name = name
  }
}

Search on Main Thread:

public func searchStocksByKeyword(keyword:String) -> [SNStock] {
  let lowercaseKeyword = keyword.lowercaseString
  var searchResults:[SNStock] = []
  searchResults = stocks.filter({ (stock:SNStock) -> Bool in
    return stock.ticker.lowercaseString.hasPrefix(lowercaseKeyword)
  })
  if (searchResults.count == 0) {
    searchResults = stocks.filter({ (stock:SNStock) -> Bool in
      return stock.name.lowercaseString.hasPrefix(lowercaseKeyword)
    })
  }
  searchResults.sortInPlace {
    ($0.ticker as String) < ($1.ticker as String)
  }
  return searchResults;
}

Search on Background Thread:

public func searchStocksByKeyword(keyword:String, completion:(stocks:[SNStock])->()) {
  let qualityOfServiceClass = QOS_CLASS_USER_INTERACTIVE
  let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
  dispatch_async(backgroundQueue, {
    let stocks:[SNStock] = self.searchStocksByKeyword(keyword)
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
      completion(stocks: stocks)
    })
  })
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM