我目前在2D数组中按字母顺序排序我的数据有一个大问题。我将尽力为您提供尽可能清晰的细节。
目前,我正在通过CNContactStore获取我的联系人。一切正常。我能够从联系人中检索出我想要的所有数据。
现在,我创建了以下结构:
struct FavoritableContact {
let contact: CNContact
var hasFavorited: Bool
}
有了这个,我声明并初始化了以下数组:
var favoritableContacts = [FavoritableContact]()
一旦我检索到我的联系人,我只需将它们附加到favitableContacts;
try store.enumerateContacts(with: request, usingBlock: { (contact, stopPointerIfYouWantToStopEnumerating) in
favoritableContacts.append(FavoritableContact(contact: contact, hasFavorited: false))
})
要在同一个数组中按字母顺序对它们进行排序,我只需执行以下操作:
var sortedContacts = favoritableContacts.sorted { $0.contact.familyName < $1.contact.familyName }
现在,如果可能的话,我想创建以下2D数组,
var 2D = [
[FavoritableContact] //"A"
[FavoritableContact], //"B"
[FavoritableContact], //"C"
[FavoritableContact], //"D"
...
]
我只是不确定如何采用我的sortedContacts数组并按字母顺序分开。
我在这里很新,如果我忘记了什么,或者我没有做对,请告诉我。
正如评论中指出的那样,首字母作为键的字典可能是更好的方式,因为它更容易访问,但也许你有理由想要使用2d数组。要做到这一点,你可以做这样的事情:
//Create an empty array filled with 26 arrays of FavorableContact
var array2d = Array<[FavoritableContact]>(repeating: [FavoritableContact](), count: 26)
//Find the ascii value for "A" to use as your base
let aAscii = Int("A".unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0]) //This returns 65, btw, so you could also just hardcode
//Go through your original array, find the first letter of each contact, and append to the correct array
favoritableContacts.forEach { (contact) in
//Get the ascii value for the first letter
let firstLetter = Int(contact.contact.familyName.prefix(1).uppercased().unicodeScalars.filter({ $0.isASCII }).map({ $0.value })[0])
//Append to the array for this letter by subtracting the ascii value for "A" from the ascii value for the uppercased version of this letter.
array2d[firstLetter - aAscii].append(contact)
}
这不是世界上最干净的东西,它采用标准英语字母表,没有变音符号,符号,数字或其他任何东西。假设这是真的,它就完成了工作。
可以使用这样的东西。
var contactsLeftToSort : [FavoritableContact] = []
var doubleArray : [[FavoritableContact]?] = [[FavoritableContact]?]()
var index : Int = 0
for char in "ABCDEFGHIJKLMNOPQRSTUV" {
doubleArray.append(nil)
var i = 0
while i < contactsLeftToSort.count {
let contact = contactsLeftToSort[i]
if contact.name.first == char {
doubleArray[index] == nil ? doubleArray[index] = [contact] : doubleArray[index]!.append(contact)
contactsLeftToSort.remove(at: i)
}
//assuming original list is alphabetized.. if not, delete this line.
if contact.name.first! > char { break }
i += 1
}
index += 1
}
正如我在上面的评论中所写,我认为你可以通过使用字典而不是数组以更优雅的方式实现这一点。
SWIFT 4
let sortedContacts: [FavoritableContact] = ... // An array of FavoritableContact objects, they should be sorted
let groupedContacts = Dictionary(grouping: contacts, by { $0.familyName.first! })
您现在拥有所有联系人的字典,其中键是字母(即A-Z),值是排序的FavoritableContact对象的数组(假设您在创建字典之前对FavoritableContacts的大数组进行了排序)。
如果您想将此作为tableview的数据源使用,则可以将所有可能的姓氏首字母的部分数量设置为。对于每个部分中的行数,您将返回该键的数组计数,如下所示:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
let letterForSection = letterForSection() // Custom method to get the section of the letter
return contactsDict[letterForSection].count
}
其余的数据源方法将以类似的方式工作。
老兄,所有这些答案真的过于复杂了。您所需要的只是以下内容:
let groupedContacts = Dictionary(grouping: contacts, by: { $0.contact.firstName.first! })
for initial, contacts in groupedContacts.lazy.sorted().{ $0.key < $1.key} {
print("#################", initial)
contacts.forEach{ print($0) }
}