我一直在将我在Java(Android)中使用的一个算法移植到Swift(iOS)中,在Swift版本上遇到了一些速度问题。
基本思想是有深度的对象(注解树),我可以通过匹配隐藏对象的列表来隐藏和显示数据集中的回复。
Top
- Reply 1
- - Reply 2
- - Reply 3
- Reply 4
并且在从数据集中隐藏之后
Top
- Reply 1
- Reply 4
我从Java转换的相关方法如下
//Gets the "real" position of the index provided in the "position" variable. The comments array contains all the used data, and the hidden array is an array of strings that represent items in the dataset that should be skipped over.
func getRealPosition(position: Int)-> Int{
let hElements = getHiddenCountUpTo(location: position)
var diff = 0
var i = 0
while i < hElements {
diff += 1
if(comments.count > position + diff && hidden.contains(comments[(position + diff)].getId())){
i -= 1
}
i += 1
}
return position + diff
}
func getHiddenCountUpTo(location: Int) -> Int{
var count = 0
var i = 0
repeat {
if (comments.count > i && hidden.contains(comments[i].getId())) {
count += 1
}
i += 1
} while(i <= location && i < comments.count)
return count
}
它与UITableViewController一起使用,以树的形式显示注解。
在Java中,使用array.contains足够快,不会导致任何延迟,但Swift版本在调用heightForRowAt
和填充单元格时多次调用getRealPosition函数,导致延迟增加,因为更多的注解id被添加到“隐藏”数组中。
有没有什么方法可以提高数组“contains”查找的速度(可能使用不同类型的集合)?我对应用程序进行了分析,“contains”是占用时间最多的方法。
谢谢你
3条答案
按热度按时间2izufjch1#
Java和Swift都必须遍历数组中包含的所有元素。随着数组变大,这会变得越来越慢。
Java的表现更好并没有什么先验的理由,因为它们都使用完全相同的算法。然而,字符串在每种语言中的实现方式都非常不同,这可能会使Swift中的字符串比较成本更高。
在任何情况下,如果字符串比较使您的速度变慢,那么您必须避免它。
简单修复:使用Set
如果你想要简单的性能提升,你可以用一个字符串集合来代替一个字符串数组。Swift中的集合是用一个哈希表来实现的,这意味着你期望的是常数时间查询。在实践中,这意味着对于大的集合,你会看到更好的性能。
为获得最佳性能:使用位集
但是,您应该能够比集合做得更好。
如果你总是以这种方式访问
hidden
,那么这意味着你所拥有的是一个从整数(i
)到布尔值(true或false)的Map。然后您应该执行以下操作...
然后您的代码将真正飞起来!
要在Swift中使用快速BitSet实现,请在
Package.swift
中包含以下内容(它是自由软件):cx6n0qe32#
我认为您需要realPosition来从tableview中某行上的tap链接到源数组?
1)创建第二个数组,其中只包含tableViewDataSource的数据
复制所有可见的元素到这个新的数组。创建一个特殊的ViewModel作为类或更好的结构,它只有必要的数据显示在tableview中。在这个新的ViewModel中保存realdataposition也作为值。现在你有一个到源数组的反向链接
2)则仅从新数据源填充此TableView
3)更多地了解swift中的
functional programming
-在那里你可以更好地学习数组,例如:或者在您的情况下:
或枚举以创建视图模型
gijlo24d3#
firstIndex(of:)!= nil比contains()快得多