Есть ли хорошее решение для поиска контактов, дублирующихся по номеру

#arrays #swift #algorithm #sorting #contacts

Вопрос:

Я попытался получить дубликаты, используя этот код

 var contactsByNumber = [CNLabeledValuelt;CNPhoneNumbergt;:[CNContact]]()    try self.store.enumerateContacts(with: fetchRequest) { [weak self] contact, stopPointerIfYouWantToStopEnumeration in    //Check contact for matching number with other contacts  for contactNumber in contact.phoneNumbers {  var contactsForNumber = contactsByNumber[contactNumber,default: []]  contactsForNumber.append(contact)  contactsByNumber[contactNumber] = contactsForNumber  print("Contacts count for number (contactNumber.value.stringValue): (contactsByNumber[contactNumber]!.count)")  print("Owner (formatter.string(from: contact))")  }  }  

И я также создал два контакта с одним и тем же номером, но он выводит, что для каждого номера в консоли есть только один контакт:

 Contacts count for number (408) 555-3514: 1 Owner Optional("Daniel Higgins Jr.") Contacts count for number 888-555-5512: 1 Owner Optional("John Appleseed") Contacts count for number 888-555-1212: 1 Owner Optional("John Appleseed") Contacts count for number 555-522-8243: 1 Owner Optional("Anna Haro") Contacts count for number (555) 766-4823: 1 Owner Optional("Hank M. Zakroff") Contacts count for number (707) 555-1854: 1 Owner Optional("Hank M. Zakroff") Contacts count for number 555-610-6679: 1 Owner Optional("David Taylor") Contacts count for number  7 (898) 222-55-22: 1 Owner Optional("FirstMatchingNumber") Contacts count for number  7 (898) 222-55-22: 1 Owner Optional("SecondMatchingNumber")  

Ответ №1:

CNLabeledValue реализация Hashable не учитывает содержащуюся в ней ценность. Каждый экземпляр имеет уникальное хэш-значение. Вы должны использовать .value вместо этого, что даст вам a CNPhoneNumber , которое, похоже, учитывает значение при хешировании, что означает, что ваши записи будут назначены одному и тому же ключу словаря:

 let number = CNLabeledValuelt;CNPhoneNumbergt;(label: nil, value: CNPhoneNumber(stringValue: "123454")) let number2 = CNLabeledValuelt;CNPhoneNumbergt;(label: nil, value: CNPhoneNumber(stringValue: "123454")) print(number.hashValue == number2.hashValue) // false print(number.value.hashValue == number2.value.hashValue) //true  

Поэтому ваш код должен быть:

 var contactsByNumber = [CNPhoneNumber:[CNContact]]()   try self.store.enumerateContacts(with: fetchRequest) { [weak self] contact, stopPointerIfYouWantToStopEnumeration in    //Check contact for matching number with other contacts  for contactNumber in contact.phoneNumbers.map({ $0.value }) {  var contactsForNumber = contactsByNumber[contactNumber,default: []]  contactsForNumber.append(contact)  contactsByNumber[contactNumber] = contactsForNumber  print("Contacts count for number (contactNumber.stringValue): (contactsByNumber[contactNumber]!.count)")  print("Owner (formatter.string(from: contact))")  } }