在 swift 中过滤数组模型字典的数组



我有一个以下格式的数据

[["B": [MerchantModel(idString: 90046, squareImageUrlString: "https:images/2017-06-30_093600_1498815360_21897", rectangleImageUrlString: "https:/2017-06-30_093613_1498815373_26005", nameString: "Burger", stateDescriptionString: "Active")]], ["C": [MerchantModel(idString: 9000014, squareImageUrlString: "https:/2017-01-24_122206_1485260526_19795", rectangleImageUrlString: "https://017-01-24_122225_1485260545_43345", nameString: "Cape Union Mart", stateDescriptionString: "Active")]], ["D": [MerchantModel(idString: 9000021, squareImageUrlString: "https:/2016-09-23_132804_1474637284_33036", rectangleImageUrlString: "https://2016-09-23_132733_1474637253_16434", nameString: "Dis-Chem", stateDescriptionString: "Active")]], ["O": [MerchantModel(idString: 9000015, squareImageUrlString: "_46238", rectangleImageUrlString: "https://2017-03-03_114409_1488541449_86767", nameString: "Old Khaki", stateDescriptionString: "Active"), MerchantModel(idString: 9001108, squareImageUrlString: "https://2015-12-08_074852_1449560932_14101", rectangleImageUrlString: "https:/2015-12-08_074924_1449560964_32669", nameString: "Outdoor Warehouse", stateDescriptionString: "Active")]], ["P": [MerchantModel(idString: 9000020, squareImageUrlString: "https://latform.images/2017-10-20_070751_1508483271_24232", rectangleImageUrlString: "https://s3-eu-west-1.ws.com/2017-10-20_070802_1508483282_60598", nameString: "Primi", stateDescriptionString: "Active")]], ["S": [MerchantModel(idString: 9001078, squareImageUrlString: "https/2015-05-26_131716_1432646236_31314", rectangleImageUrlString: "https://s3-eu-west-1.amazonaws.com/co.wigroup.global.wiplatform.images/2015-05-26_131726_1432646246_38768", nameString: "Steers", stateDescriptionString: "Active"), MerchantModel(idString: 9001102, squareImageUrlString: "https://s3-eu-west-1.amazonaws.com/co.wigroup.global.wiplatform.images/2015-11-04_102848_1446632928_54414", rectangleImageUrlString: "https://s3-eu-west-1.amazonaws.com/co.wigroup.global.wiplatform.images/2015-11-04_102909_1446632949_10764", nameString: "Sportsmans Warehouse", stateDescriptionString: "Active")]], ["T": [MerchantModel(idString: 9000051, squareImageUrlString: "https://s3-eu-west-1.amazonaws.com/co.wigroup.global.wiplatform.images/2017-02-27_122839_1488198519_16635", rectangleImageUrlString: "https://s3-eu-west-1.amazonaws.com/co.wigroup.global.wiplatform.images/2017-02-27_122858_1488198538_28922", nameString: "Tread and Miller", stateDescriptionString: "Active"), MerchantModel(idString: 9001132, squareImageUrlString: "https://s3-eu-west-1.amazonaws.com/co.wigroup.global.wiplatform.images/2016-10-25_112853_1477394933_57183", rectangleImageUrlString: "2016-10-25_112909_1477394949_90719", nameString: "Total", stateDescriptionString: "Active"), MerchantModel(idString: 9001168, squareImageUrlString: "/2017-05-02_133525_1493732125_25733", rectangleImageUrlString: "2017-05-02_133546_1493732146_85357", nameString: "Toys R Us", stateDescriptionString: "Active"), MerchantModel(idString: 9001170, squareImageUrlString: "2017-05-11_090202_1494493322_33697", rectangleImageUrlString: "2017-05-11_090539_1494493539_29021", nameString: "Toy Kingdom", stateDescriptionString: "Active")]]]

其中MerchantModel是模型类,如下所示

struct MerchantModel {
let idString : UInt
var squareImageUrlString : String
let rectangleImageUrlString : String
let nameString : String
let stateDescriptionString : String
}

我必须在UISearchbar中对给定的数据执行搜索,我写在下面的代码中

//MARK:- 搜索商家和重新加载表

func filter(array : [[String : [MerchantModel]]], byString filterString : String) {
let searchByNamesArray = array.filter { $0.values.contains { $0.contains { $0.nameString.lowercased().contains(filterString.lowercased())} } }
//Assign searched array into arrayOfMerchants
self.arrayOfMerchants = searchByNamesArray
//Reload table with new Data
self.merchantTableView.reloadData()
}

上述搜索方法适用于少数情况,在搜索栏中说"Bu"并返回"汉堡",但如果我在搜索栏中输入"Tr",我会得到错误的搜索。

请建议我在搜索数据时做错了什么。

如果我必须解释我的问题,请告诉我。

首先,数据格式(分别包含一个键值对的字典数组(效率非常低。包含所有[String:[MerchantModel]]的单个字典或包含所有MerchantModel项的单个数组效率要高得多。

尽管如此,过滤此格式的一种可能的有效方法是首先获取前缀字母的相应字典,然后过滤值。

func filter(array : [[String : [MerchantModel]]], byString filterString : String) {
var searchByNamesArray = [MerchantModel]()
if let firstChar = filterString.first {
let prefix = String(firstChar)
if let modelDictionary = array.first(where: { $0[prefix] != nil }) {
searchByNamesArray = modelDictionary[prefix]!.filter({$0.nameString.range(of: filterString, options:[.caseInsensitive, .diacriticInsensitive]) != nil })
} 
}
//Assign searched array into arrayOfMerchants
self.arrayOfMerchants = searchByNamesArray
//Reload table with new Data
self.merchantTableView.reloadData()
}
searchByNamesArray

的问题在于它会返回一个字典数组,在这种情况下,它是带有"T"键的字典。后者包含许多可能与您的搜索词不匹配的商家。

以下是您应该如何操作:

let merchants: [MerchantModel] = data
.map {Array($0.values)}
.flatMap{$0}
.flatMap{$0}
.filter {$0.nameString.contains("Tr")}

所以当用户搜索"Tr"时,结果会"Tread and Miller"

let merchants: [MerchantModel] = data.map {Array($0.values)}.flatMap{$0}.flatMap{$0}.filter {$0.nameString.contains("Tr")}
merchants.forEach {print($0.nameString)} //Tread and Miller

最新更新