如何按字母顺序对二维数组中的数据进行排序?

问题描述 投票:3回答:4

我目前在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数组并按字母顺序分开。

我在这里很新,如果我忘记了什么,或者我没有做对,请告诉我。

ios arrays swift sorting
4个回答
0
投票

正如评论中指出的那样,首字母作为键的字典可能是更好的方式,因为它更容易访问,但也许你有理由想要使用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)
}

这不是世界上最干净的东西,它采用标准英语字母表,没有变音符号,符号,数字或其他任何东西。假设这是真的,它就完成了工作。


0
投票

可以使用这样的东西。

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
}

0
投票

正如我在上面的评论中所写,我认为你可以通过使用字典而不是数组以更优雅的方式实现这一点。

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
}

其余的数据源方法将以类似的方式工作。


0
投票

老兄,所有这些答案真的过于复杂了。您所需要的只是以下内容:

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) }
}
© www.soinside.com 2019 - 2024. All rights reserved.