• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ios - Swift - 根据多个条件搜索大型数组

[复制链接]
菜鸟教程小白 发表于 2022-12-11 18:26:34 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我有一个 4K+ 项目的数组,使用 UISearchBar 和 UISearchController 对列表进行排序以进行匹配。我想通过几个标准来排序数组,但最重要的是用户首先输入的顺序

搜索 Controller 有 3 个范围按钮

  • 类别
  • 子类别
  • 所有猫

搜索数组中的项目是使用结构类来访问条件的:

struct Item {
    var title: String
    var category: String
    var subCategory: String
    var allCat: String
}

标准的过滤方法是这样的:

func filterContentForSearchText(_ searchText: String, scope: String = "All") {

    self.filteredItems = allItems.filter({( item : Item) -> Bool in

        let categoryMatch = (item.allCat == scope) || (item.category == scope)
        return categoryMatch && item.title.lowercased().contains(searchText.lowercased())
        //return categoryMatch && (item.title.lowercased().range(of:searchText.lowercased()) != nil)
    })

    tableView.reloadData()
}

这在项目很少的情况下很好,但如果我有很大的数组并且使用上面的 block 时,将包含大量不相关的项目,其中包含键入的字符串。

我可以通过 BEGINSWITH 使用谓词来获得更好的结果,但我无法满足类别的条件。我很确定下面的代码块无效,并希望获得更多经济建议。另一个障碍是数组包含多个单词的字符串。例如:

array = ["Apple", "Apple Freshly Picked", "Apple Green", "ear", "Melon", "ear Yellow",....]

所以当用户开始输入“Ap”时的结果应该是

  • 苹果
  • 苹果绿
  • 新鲜采摘的苹果

我在不满足搜索类别(结构)条件的情况下让它工作:

func filterContentForSearchText(_ searchText: String, scope: String = "All") {

    let words = searchText.components(separatedBy: " ")

    var word1 = ""
    var word2 = ""
    var word3 = ""

    var predicate = NSPredicate()
    var array = [Item]()

    if scope == "All" {

        if words.count == 1{
            word1 = (words[0])
            predicate = NSPredicate(format: "SELF BEGINSWITH[cd] %@ OR SELF LIKE[cd] %@", word1, word1)
        }
        else if words.count == 2{
            word1 = (words[0])
            word2 = (words[1])
            predicate = NSPredicate(format: "SELF BEGINSWITH[cd] %@ AND SELF CONTAINS[cd] %@", word1, word2)
        }
        else if words.count == 3{
            word1 = (words[0])
            word2 = (words[1])
            word3 = (words[2])
            predicate = NSPredicate(format: "SELF BEGINSWITH[cd] %@ AND SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@", word1, word2, word3)
        }

    } else {

        predicate = NSPredicate(format: "title BEGINSWITH[cd] %@ AND category == %@", searchText, scope)

        if words.count == 1{
            word1 = (words[0])
            predicate = NSPredicate(format: "SELF BEGINSWITH[cd] %@ OR SELF LIKE[cd] %@ AND category == %@", word1, word1, scope)
        }
        else if words.count == 2{
            word1 = (words[0])
            word2 = (words[1])
            predicate = NSPredicate(format: "SELF BEGINSWITH[cd] %@ AND SELF CONTAINS[cd] %@ AND category == %@", word1, word2, scope)
        }
        else if words.count == 3{
            word1 = (words[0])
            word2 = (words[1])
            word3 = (words[2])
            predicate = NSPredicate(format: "SELF BEGINSWITH[cd] %@ AND SELF CONTAINS[cd] %@ AND SELF CONTAINS[cd] %@ AND category == %@", word1, word2, word3, scope)
        }

    }

    array = (allItems as NSArray).filtered(using: predicate) as! [Item]
    self.filteredItems = array

    let lengthSort = NSSortDescriptor(key: "length", ascending: true)
    let sortedArr = (self.filteredItems as NSArray).sortedArray(using: [lengthSort])
    self.filteredItems = sortedArr as! [Item]

    self.tableView.reloadData()
}

请问我该如何处理满足类别以及输入字符串匹配和字符串(第一个单词)的长度/范围的逻辑?

谢谢



Best Answer-推荐答案


我找到了路。我结合了 .filter 和 .sort 来得到结果:

func filterContentForSearchText(_ searchText: String, scope: String = "All") {

    let options = NSString.CompareOptions.caseInsensitive

    if scope == "All"{

        print("filtering All")
        self.filteredItems = allItems
            .filter{$0.title.range(of: searchText, options: options) != nil && $0.allCat == scope}
            .sorted{ ($0.title.hasPrefix(searchText) ? 0 : 1) < ($1.title.hasPrefix(searchText) ? 0 : 1) }
    }
    else{

        print("filtering \(scope)")
        self.filteredItems = allItems
            .filter{$0.title.range(of: searchText, options: options) != nil && $0.category == scope}
            .sorted{ ($0.title.hasPrefix(searchText) ? 0 : 1) < ($1.title.hasPrefix(searchText) ? 0 : 1) }

    }
    tableView.reloadData()
}

希望这对某人有所帮助

关于ios - Swift - 根据多个条件搜索大型数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45521911/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap