【问题标题】:Improve comparison of two arrays Swift改进两个数组 Swift 的比较
【发布时间】:2019-02-02 11:51:30
【问题描述】:

我有一个应用程序,用户可以在其中单击其他用户个人资料,然后该应用程序将比较两个用户的电话联系人并搜索常用联系人。这行得通,但它会消耗很多时间,所以我想知道有没有办法至少可以加快一点速度。

****注意我是 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"
            }

谢谢。

【问题讨论】:

  • 与您的问题无关,但这些属性真的是可选的吗?为什么不使用结构?顺便说一句,不再需要自己实现 hashValue 了。 struct Contact: Hashable, Equatable { let name: String let phoneNumber: String let thumbnail: Data let filled: Bool }这就是你所需要的
  • 与您的问题无关,但电话号码上的字符串比较不会导致误报吗?例如"020-12312312" != "02012312312"。 PhoneNumber 应该是一个处理这类东西的类。
  • @LeoDabus 谢谢我改成了struct
  • @Yupi 是的,我确实这么认为,Strings 基本上是由整数表示的字符数组,因此两个字符串的比较很可能实现为多个字符(整数)比较。但是,哈希值的计算会产生开销。我看到您从不存储哈希值,而是在每次访问时计算它。也许您应该将 hashValue 属性更改为 lazy var

标签: ios arrays swift performance


【解决方案1】:

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

将一个数组中的电话号码复制到一个集合中,并使用Setcontains(_:), 函数,该函数具有非常接近于常数时间的性能,给你一共O(n)的性能,多, 好多了

【讨论】:

    【解决方案2】:

    contacts 是一个数组有什么原因吗?我会使用Set<Contact>,因为您可以轻松地执行集合操作。

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

    【讨论】:

      【解决方案3】:

      您可以尝试与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.
          })
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        相关资源
        最近更新 更多