改进两个数组的比较Swift

时间:2018-08-27 22:40:12

标签: ios arrays swift performance

我有一个应用程序,用户可以单击其他用户个人资料,然后该应用程序将在两个用户的电话联系人之间进行比较并搜索常见联系人。那行得通,但是要花很多时间,所以我想知道是否有办法至少可以加快一点速度。

****请注意,我是iOS开发的初学者,总体上对Swift语法和iOS还是不太熟悉,因此非常感谢您提供任何帮助

这是我简单的Contact类:

class Contact: Hashable, Equatable {
  var hashValue: Int { get { return phoneNumber!.hashValue } }
  var name: String?
  var phoneNumber: String?
  var thumbnail: Data?
  var filled: Bool?

  init() {
  }

  init(name: String?, phoneNumber: String?, thumbnail: Data?) {
    self.name = name
    self.phoneNumber = phoneNumber
    self.thumbnail = thumbnail
}
static func ==(lhs: Contact, rhs: Contact) -> Bool {
    return lhs.phoneNumber == rhs.phoneNumber
  }
}

如您所见,我已经实现了HashableEquatable,它们用于通过电话号码比较联系人并删除重复的联系人。这是我执行比较主要操作的代码。 contacts数组包含用户的电话联系人,otherContacts是其他用户的电话联系人的数组。

                for result in self.contacts {
                if self.otherContacts.contains(result){
                    self.commonContacts.append(result)
                }
            }
            self.removedDuplicates = Array(Set(self.commonContacts))
            if self.removedDuplicates.count == 1 {
                self.commonFriends.text = "\(1) common friend"
            }
            else {
                self.commonFriends.text = "\(self.removedDuplicates.count) common friends"
            }

谢谢。

3 个答案:

答案 0 :(得分:2)

请问有什么原因可以使联系人成为数组?我将使用class ContentFeedDataSource() : ItemKeyedDataSource<Date, Content>() { override fun loadBefore(params: LoadParams<Date>, callback: LoadCallback<Content>) {} override fun getKey(item: Content) = item.timestamp override fun loadInitial(params: LoadInitialParams<Date>, callback: LoadInitialCallback<Content>) { FirestoreCollections.contentCollection .collection(FirestoreCollections.ALL_COLLECTION) .orderBy(Constants.TIMESTAMP, Query.Direction.DESCENDING) .whereGreaterThanOrEqualTo(Constants.TIMESTAMP, DateAndTime.getTimeframe(WEEK)) .limit(params.requestedLoadSize.toLong()) .get().addOnCompleteListener { val items = arrayListOf<Content?>() for (document in it.result.documents) { val content = document.toObject(Content::class.java) items.add(content) } callback.onResult(items.sortedByDescending { it?.qualityScore }) } } override fun loadAfter(params: LoadParams<Date>, callback: LoadCallback<Content>) { FirestoreCollections.contentCollection .collection(FirestoreCollections.ALL_COLLECTION) .orderBy(Constants.TIMESTAMP, Query.Direction.DESCENDING) .startAt(params.key) .whereGreaterThanOrEqualTo(Constants.TIMESTAMP, DateAndTime.getTimeframe(WEEK)) .limit(params.requestedLoadSize.toLong()) .get().addOnCompleteListener { val items = arrayListOf<Content?>() for (document in it.result.documents) { val content = document.toObject(Content::class.java) items.add(content) } val sortedByQualityScore = ArrayList(items.sortedByDescending { it?.qualityScore }) callback.onResult(sortedByQualityScore) sortedByQualityScore.clear() } } } ,因为您可以轻松地执行设置操作。

要获得每个集合的公共元素,假设您的哈希码实现正确,只需使用Set.intersection(_:)

答案 1 :(得分:2)

对于数组,包含具有O(n)性能。因此,将一个数组中的所有元素与另一个数组进行检查具有O(n^2)(n平方)的性能,这很糟糕。

将电话号码从一个数组复制到一组中,并使用Set的{​​{1}}函数,该函数具有非常接近恒定时间的性能,总共为您提供contains(_:)性能,好很多好。

答案 2 :(得分:1)

您可以尝试与Dictionary合并,这可能会给您带来帮助。

var commonContacts = Dictionary(uniqueKeysWithValues: contacts.lazy.map{ return ($0.phoneNumber!, $0) })
    .merge(otherContacts.lazy.map{ ($0.phoneNumber!, $0) }, uniquingKeysWith: {
        contact1, _ in contact1 // Can do merging of duplicates here.
    })