I have Dictionary which contains String keys and Array of Objects as value. These values are added from the sorted Array of objects into Dictionary using append method. The values are categorized into keys based on the first letter of object property. But returns unsorted Dictionary.
The dictionaries are declared:
var namesDic = [String: [Name]]()
var filteredNames = [String: [Name]]()
And iterating through array and appending into Dictionary:
for name in names {
let letterIndex = name.getName().index(name.getName().startIndex, offsetBy: 0)
let letter = name.getName()[letterIndex]
if namesDic[String(letter)] != nil {
namesDic[String(letter)]?.append(name)
} else {
namesDic[String(letter)] = [name]
}
}
filteredNames = namesDic
}
Name structure:
struct Name {
var id: Int!
var name: String!
var native: String!
var meaning: String!
var origin: String!
var isFavorite: Bool
var gender: String!
init(id: Int, name: String, native: String, meaning: String, origin: String, isFavorite: Int, gender: String) {
self.id = id
self.name = name
self.native = native
self.meaning = meaning
self.origin = origin
if isFavorite == 0 {
self.isFavorite = false
} else { self.isFavorite = true }
self.gender = gender
}
}
I found in debugging that they are unsorted when they are appended to dictionary. I understand sort on Swift Dictionary is not working but I want a work around to sort Dictionary by key to pass it to TableView.
I went through many questions/answers here but they are all for [String: String]
not Array of Objects.
struct Name: CustomStringConvertible {
let id: Int
let name: String
let native: String
let meaning: String
let origin: String
let isFavorite: Bool
let gender: String
var description: String {
return "Id: " + String(id) + " - Name: " + name
}
}
let name1 = Name(id: 1, name: "Tim Cook", native: "native", meaning: "meaning", origin: "origin", isFavorite: true, gender: "Male")
let name2 = Name(id: 2, name: "Steve Jobs", native: "native", meaning: "meaning", origin: "origin", isFavorite: true, gender: "Male")
let name3 = Name(id: 3, name: "Tiger Woods", native: "native", meaning: "meaning", origin: "origin", isFavorite: true, gender: "Male")
let name4 = Name(id: 4, name: "Socrates", native: "native", meaning: "meaning", origin: "origin", isFavorite: true, gender: "Male")
let names = [name1, name2, name3, name4]
let dictionary = names.sorted(by: {$0.name < $1.name }).reduce(into: [String: [Name]]()) { result, element in
// make sure there is at least one letter in your string else return
guard let first = element.name.first else { return }
// create a string with that initial
let initial = String(first)
// initialize an array with one element or add another element to the existing value
result[initial, default: []].append(element)
}
let sorted = dictionary.sorted {$0.key < $1.key}
print(sorted) // "[(key: "S", value: [Id: 4 - Name: Socrates, Id: 2 - Name: Steve Jobs]), (key: "T", value: [Id: 3 - Name: Tiger Woods, Id: 1 - Name: Tim Cook])]\n"
According to Apple's documentation
A dictionary stores associations between keys of the same type and
values of the same type in a collection with no defined ordering. Each
value is associated with a unique key, which acts as an identifier for
that value within the dictionary. Unlike items in an array, items in
a dictionary do not have a specified order. You use a dictionary
when you need to look up values based on their identifier, in much the
same way that a real-world dictionary is used to look up the
definition for a particular word.
Further information is available on Apple's Website
Workaround
One thing that could be done is to create an array of sorted keys and then use that array to access the dictionary values