0

I am fetching data from model i.e Contacts. Then I sort this model as per nameproperty. But the result is not come in sorted manner. I am using following code to sort data:

 func filterArrayAlphabatically(contacts : [Contact])
    {

        let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.map({ String($0)})

        let all_Contacts =  contacts.sorted { $0.name < $1.name } //Sort model data as per name

        var result = [String:[Contact]]()

        for letter in alphabet
        {
            result[letter] = []

            for cntct in all_Contacts
            {
                let ctc : Contact! = cntct 
                let name : String! = ctc.name.capitalized

                if name.hasPrefix(letter)
                {
                  result[letter]?.append(cntct)
                }
            }
        }

        print("result......\(result)")
    }

It gives me output like:

result......["M": [], "K": [<App.Contact: 0x7c6703e0>], "E": [], "U": [], "Y": [], "H": [<App.Contact: 0x7c6701a0>], "X": [], "A": [<App.Contact: 0x7c670120>, <App.Contact: 0x7c670440>], "D": [<App.Contact: 0x7c6700b0>, <App.Contact: 0x7c670160>], "I": [], "R": [], "G": [], "P": [], "O": [], "L": [], "W": [], "C": [], "V": [], "J": [<App.Contact: 0x7c66f990>], "Q": [], "T": [], "B": [], "N": [], "Z": [], "S": [], "F": []]

I want output in sorted manner like:

 result......["A": [], "B": [<App.Contact: 0x7c6703e0>], "C": [], "D": []]

What I am doing wrong? Or Is there any other to sort it. Thanks!

EDIT: I tried following code to make correct order:

let sortedArray = result.sorted
    {
        (struc1, struc2) -> Bool in
        return struc1.key < struc2.key
    }

Ok, this gives me result in correct order as I want. But the problem is I want to use it, But How I don't know. As I have var arr_Contacts = [String:[Contact]]() . I want to assign sortedArray to arr_Contacts. How Can I do that?

When I assign it gives warning that is:

enter image description here

It gives error:

enter image description here

3
  • 3
    You are putting the results into a dictionary, keyed by the first letter. Dictionaries are unordered. Commented Jan 19, 2017 at 8:18
  • you may want to look into using an NSOrderedDictionary Commented Jan 19, 2017 at 8:19
  • Yes, how can I make it in correct order? Commented Jan 19, 2017 at 8:21

2 Answers 2

1

As others have said, a dictionary is unordered - if you need an ordered representation of your data, you've chosen the wrong data structure. An array is much better suited for ordered representations.

Make an array of dictionaries, or simple structs, which combine a starting letter with an array of contacts that begin with that letter.

func filterArrayAlphabatically(contacts inputContacts: [Contact]) -> [[String: [Contact]]]
{
    //Using this will remove any contacts which have a name not beginning with these letters, is that intended?
    let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.map({ String($0) })

    // For strings use a localized compare, it does sensible things with accents etc.
    let allContacts = inputContacts.sorted { $0.name.localizedCompare($1.name) == .orderedAscending }

    //Now we're using an array of dictionaries, each of which will have a single key value pair [letter: [Array of contacts]]
    var result = [[String: [Contact]]]()

    for letter in alphabet
    {
        result.append([letter: contacts(beginningWith: letter, from: allContacts)])
    }

    return result
}

func contacts(beginningWith prefix: String, from contactList: [Contact]) -> [Contact] {
    //you could use a filter here for brevity, e.g.
    //let contacts = contactList.filter { $0.name.capitalized.hasPrefix(prefix) }
    //this is short enough to reasonably be used at the call site and not within a function

    var contacts = [Contact]()
    for contact in contactList {
        if contact.name.capitalized.hasPrefix(prefix) {
            contacts.append(contact)
        }
    }
    return contacts
}

let contacts = [Contact(name: "Bob"), Contact(name: "Kate"), Contact(name: "Darling")]
let filteredArray = filterArrayAlphabatically(contacts: contacts)
print(filteredArray)
//[["A": []], ["B": [Contact(name: "Bob")]], ["C": []], ["D": [Contact(name: "Darling")]], ["E": []], ["F": []], ["G": []], ["H": []], ["I": []], ["J": []], ["K": [Contact(name: "Kate")]], ["L": []], ["M": []], ["N": []], ["O": []], ["P": []], ["Q": []], ["R": []], ["S": []], ["T": []], ["U": []], ["V": []], ["W": []], ["X": []], ["Y": []], ["Z": []]]
Sign up to request clarification or add additional context in comments.

Comments

1

Try to sort with this formating.

class Contact {
    var name: String = ""
    var lastName: String = ""

    public init (name: String, lastName: String ){
        self.name = name
        self.lastName = lastName
   }
}

let contact1 = Contact(name: "V", lastName: "W")
let contact2 = Contact(name: "G", lastName: "W")
let contact3 = Contact(name: "A", lastName: "C")
let contact4 = Contact(name: "P", lastName: "W")
let contact5 = Contact(name: "F", lastName: "W")
let contact6 = Contact(name: "A", lastName: "W")
let contact7 = Contact(name: "A", lastName: "W")
var contacts: [Contact]

contacts = [contact1, contact2, contact3, contact4, contact5, contact6, contact7]

let sortedContact = contacts.sorted{(struct1, struct2) -> Bool in
    return struct1.name < struct2.name
}
//At this point our contact are sorted, now add to dictionnary

var arr_Contacts = [String:[Contact]]()
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".characters.map({ String($0) })

for letter in alphabet {
    arr_Contacts[String(letter)] = []
    let matches = sortedContact.filter({$0.name.characters.first == letter.characters.first})
    if !matches.isEmpty {
        for contact in matches {
            arr_Contacts[letter]?.append(contact)
        }
    }
}
//Dic are unordered data, so need to use an Array
let sortedDic = Array(arr_Contacts).sorted{ (s1,  s2) in
    return s1.key < s2.key
}

Output :

("A", [Contact, Contact, Contact])("B", [])("C", [])("D", [])("E", [])("F", [Contact])("G", [Contact])("H", [])("I", [])("J", [])("K", [])("L", [])("M", [])("N", [])("O", [])("P", [Contact])("Q", [])("R", [])("S", [])("T", [])("U", [])("V", [Contact])("W", [])("X", [])("Y", [])("Z", [])

3 Comments

I have var arr_Contacts = [String:[Contact]]() and how can I assign this sortedArray to arr_Contacts.
look your output is not sorted. Isn't it?
@Amanpreet ordered a Dict ? Just use an array... come on... check my edit

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.