过滤结果,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) && !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 性能变慢的主要内容,如果未能解决你的问题,请参考以下文章