【问题标题】:Filter results, slow performance Swift过滤结果,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 }
  • 您可以通过将所有条件放在一个过滤器语句中,在 一次通过 中完成所有过滤。

标签: swift filter userdefaults


【解决方案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))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多