Search code examples
swiftnsarraynsdictionary

How to sort an Array with conditions in Swift 3


I'm having an Array of CNContact. I need them to be sorted by name to have tableView sections sorted by name.

var sortedContactsDictionary: [String: [CNContact]] = [:]
var alphabeticSortedContacts: [CNContact] = []

func setAlphabeticOrderOfContacts(_ contact: CNContact) {
    var name = ""
    if contact.familyName != "" {
        name = contact.familyName.lowercaseFirst
    } else {
        name = contact.givenName.lowercaseFirst
    }

    let currentLetter = name.characters.first

    if self.lastProcessedLetter == nil || self.lastProcessedLetter == currentLetter {
        self.alphabeticSortedContacts.append(contact)
    } else {
        self.alphabeticSortedContacts.removeAll()
        self.alphabeticSortedContacts.append(contact)
    }

    self.lastProcessedLetter = currentLetter

    if let letter = currentLetter {
        self.sortedContactsDictionary["\(letter)"] = self.alphabeticSortedContacts
    }
}

But my problem is, that some of the familyName values contain special character like ( as the first character.

Since the [CNContact] is already sorted, the special character names are sorted where I don't need them and if I do something like this:

let specialCharactersRemoved = name.replacingOccurrences(of: "(", with: "")
let currentLetter = specialCharactersRemoved.characters.first

My sections aren't in order anymore. I have the "second letter" of the name (after () for example as first letter of the sections instead of the desired A and if I sort the dictionary again, I have multiple times a section with (f.e.) the key S.

What am I missing or what would be a better approach to sort the [CNContact] into [String: [CNContact]]? Help is very appreciated.


Solution

  • I have re-coded my function and now I append on existing keys and create a new Array on missing keys.

    func setAlphabeticOrderOfContacts(_ contact: CNContact) {
        if let letter = self.getCurrentLetter(contact) {
            let keyExists = self.sortedContactsDictionary["\(letter)"] != nil
    
            if keyExists {
                var arrayOfContacts = self.sortedContactsDictionary["\(letter)"]
                arrayOfContacts?.append(contact)
                self.sortedContactsDictionary["\(letter)"] = arrayOfContacts
            } else {
                var arrayOfContacts = [CNContact]()
                arrayOfContacts.append(contact)
                self.sortedContactsDictionary["\(letter)"] = arrayOfContacts
            }
        }
    }
    
    func getCurrentLetter(_ contact: CNContact) -> Character? {
        var name = String()
        if contact.familyName != "" {
            name = contact.familyName
        } else {
            name = contact.givenName
        }
    
        let specialCharactersRemoved = name.replacingOccurrences(of: "(", with: "").lowercaseFirst
        let currentLetter = specialCharactersRemoved.characters.first
        guard let letter = currentLetter else { return nil }
        return letter
    }