过滤结果,Swift 性能变慢

Posted

技术标签:

【中文标题】过滤结果,Swift 性能变慢【英文标题】:Filter results, slow performance Swift 【发布时间】:2021-10-27 18:55:23 【问题描述】:

斯威夫特问题... 我正在制作一个 babyname 应用程序并尝试过滤用户选择的结果。我设法让它工作,但需要一段时间才能过滤结果。我的意思是 2-3 秒。

这是我写的:

func apply(list: [String]) -> [String] 
        let allSavedSettings = settings.all

        var newList = list
        
        if let short = allSavedSettings["short"] as? Bool 
            if !short 
                print("filter short")
                newList = newList.filter($0.count > 4)
            
        
        if let long = allSavedSettings["long"] as? Bool 
            if !long 
                print("filter long")

                newList = newList.filter($0.count < 5)
            
        
        if let dutch = allSavedSettings["dutch"] as? Bool 
            if !dutch 
                print("filter dutch")

                newList = newList.filter(!dutchboy.contains($0))
                newList = newList.filter(!dutchgirl.contains($0))
            
        
        if let english = allSavedSettings["english"] as? Bool 
            if !english 
                print("filter english")

                newList = newList.filter(!englishboy.contains($0))
                newList = newList.filter(!englishgirl.contains($0))
                
            
        
        if let arabic = allSavedSettings["arabic"] as? Bool 
            if !arabic 
                print("filter arabic")

                newList = newList.filter(!arabicboy.contains($0))
                newList = newList.filter(!arabicgirl.contains($0))
                
            
        
        if let hebrew = allSavedSettings["hebrew"] as? Bool 
            if !hebrew 
                print("filter hebrew")

                newList = newList.filter(!hebrewboy.contains($0))
                newList = newList.filter(!hebrewgirl.contains($0))
                
            
        
        if let latin = allSavedSettings["latin"] as? Bool 
            if !latin 
                print("filter latin")

                newList = newList.filter(!latinboy.contains($0))
                newList = newList.filter(!latingirl.contains($0))
                
            
        
        if let chinese = allSavedSettings["chinese"] as? Bool 
            if !chinese 
                print("filter chinese")

                newList = newList.filter(!chineseboy.contains($0))
                newList = newList.filter(!chinesegirl.contains($0))
                
            
        
        if let scandinavian = allSavedSettings["scandinavian"] as? Bool 
            if !scandinavian 
                print("filter scandinavian")

                newList = newList.filter(!scandinavianboy.contains($0))
                newList = newList.filter(!scandinaviangirl.contains($0))
                
            
        
        if let spanish = allSavedSettings["spanish"] as? Bool 
            if !spanish 
                print("filter spanish")

                newList = newList.filter(!spanishboy.contains($0))
                newList = newList.filter(!spanishgirl.contains($0))
                
            
        
        
        return newList
    

因此,我将用户首选项作为布尔值保存在名为“allSavedSettings”的数组中,并带有用户默认值。每当设置为 false 时,它​​都会从完整的名称列表中过滤结果。

还有什么我应该使用的东西来加快速度吗?该列表大约有 5000 个名字。

提前致谢。

帕特里克

【问题讨论】:

至少,您可以通过组合您的语句将一切速度提高 2 倍。例如newList = newList.filter( !dutchboy.contains($0) &amp;&amp; !dutchgirl.contains($0) )。我也会对所有内容使用Set 而不是Array - 假设所有项目都是独一无二的,应该会导致相当大的加速。我也会尝试所有 Swift 编译优化。 @jnpdx 哇当然。我编写它的方式将通过整个数组两次而不是现在一次。这已经很有效了。谢谢。我想我会使用一个数组,因为元素的顺序有时很重要。例如,我有一个方法可以在列表中的某个索引处插入一个新名称。或者这在 Set 中也是可能的吗? Apple 的 Swift Collections 包包括 OrderedSet: github.com/apple/swift-collections 它仍然不应该花费 3 秒。整个数据结构似乎设计得很糟糕。名称应该类似于 struct Name let value = "the actual name"; let isDutch: Bool; let isSpanish: Bool 您可以通过将所有条件放在一个过滤器语句中,在 一次通过 中完成所有过滤。 【参考方案1】:

我会尽可能使用集合,因为散列比多次迭代数组要快,而且它消除了重复。您无需将主列表转换为集合,因为这会增加额外的周期。

这样的事情应该会加快速度。

var doNotInclude = Set<String>()
        
if allSavedSettings["english"] == false 
    doNotInclude.formUnion(Set(englishBoy + englishGirl))


if allSavedSettings["dutch"] == false 
    doNotInclude.formUnion(Set(dutchBoy + dutchGirl))


if allSavedSettings["arabic"] == false 
    doNotInclude.formUnion(Set(arabicBoy + arabicGirl))


let result = list.filter  !doNotInclude.contains($0) 

【讨论】:

将数组更改为 Set 有效。我不得不改回数组,因为有时我需要对名称进行排序。我还注意到使用 .filter 比使用 .subtracting(doNotInclude) 花费更多时间。所以我使用了类似result = Array(list.subtracting(doNotInclude))

以上是关于过滤结果,Swift 性能变慢的主要内容,如果未能解决你的问题,请参考以下文章

连接中过滤器的 SQL 性能与结果中的 SQL 性能

使用文件排序的 MYSQL 性能变慢

什么可能导致函数导入性能变慢?

生产环境服务器变慢,诊断思路和性能评估

使用 group by 聚合计数 > 100 万用户 的 Mysql 查询性能变慢

使用 WebBrowser 控件时 IE 11 WebGL 性能变慢