【问题标题】:How to sort the data in in a twoDimensional array alphabetically?如何按字母顺序对二维数组中的数据进行排序?
【发布时间】:2018-01-02 19:18:58
【问题描述】:

我目前在二维数组中按字母顺序排序我的数据时遇到了一个大问题。我将尽力为您提供每一个细节,以使其尽可能清晰。

目前,我正在使用 CNContactStore 获取我的联系人。这一切都很好。我能够从我的联系人中检索我想要的所有数据。

现在,我创建了以下结构:

struct FavoritableContact {
    let contact: CNContact
    var hasFavorited: Bool
}

有了这个,我声明并初始化了以下数组:

var favoritableContacts = [FavoritableContact]()

一旦我检索到我的联系人,我只需将它们附加到 favouritableContacts;

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 }

现在,如果可能,我想创建以下二维数组,

var 2D = [
        [FavoritableContact] //"A"
        [FavoritableContact], //"B"
        [FavoritableContact], //"C"
        [FavoritableContact], //"D"
        ...
    ]

我只是不确定如何获取我的 sortedContacts 数组并按字母顺序分隔。

我是新来的,如果我忘记了什么,或者我做的不对,请告诉我。

【问题讨论】:

  • 与其拥有像上面创建的二维数组那样的数组,不如创建一个字典来保存按字母顺序排列的联系人更有意义。因此,创建一个字典,其中键是字母(“a”、“b”、“c”等),值是按字母顺序排序的 FavoritableContact 数组。您可以通过循环访问您的联系人并检查 familyName 的第一个字母来创建此字典。
  • 这就是我想做的事情。但我期待将联系人放在表格视图中。因此,我会使用 section 和 row 来遍历 2D 数组并将其显示在 tableview 上。
  • 您仍然可以使用字典作为 tableView 的数据源。您可以简单地使用带有字母的数组来保持字母的有序列表,并且在您的 tableView 方法中,您可以获得键“A”的数组计数,例如,了解有多少“A”与您联系有,等等。
  • tableview 的数据源不必是数组。事实上,字典是 tableview 集合的一个非常常见的数据源。在您的情况下,我假设这些部分将是第一个字母(A-Z),而行将是作为值存储在您的字典中的数组。如果键不存在,则部分将为空。

标签: ios arrays swift sorting


【解决方案1】:

正如 cmets 中所指出的,以首字母作为键的字典可能是更好的方法,因为它更容易访问,尽管您可能有理由想要使用二维数组。为此,您可以执行以下操作:

//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)
}

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

【讨论】:

  • 这就是人.. 非常感谢!不过,您能否详细说明您是如何处理 aAscii 的?我不明白那条线! thxxx!
  • 不是每个人的名字都以拉丁字母的 A-Z 开头。
  • @JavierV。是的:A 的 ascii 值是 65,B 是 66,等等。因此,由于我们需要将字母表转换为字母表的数组索引,我们需要使 A 为 0,B 为 1,等等。所以一旦我们知道 A 是 65我们可以从每个字母的 ascii 值中减去 65 来实现这一点。您也可以只制作一个更大的数组来保存所有 ascii 可能性,然后您不必这样做,但我的代码只是一个示例。您可能需要更多地考虑这一点,因为可能会出现其他角色,但这会让您入门。
  • @Alexander 是的,我在回答中也提到了这一点。这并不是一个全面的解决方案——只是提问者如何开始的一个例子。
  • @creeperspeak 完美的男人!现在,我能够检查 ascii 表中和键盘上可用的每个字符。唯一的问题是我缺少其他语言和表情符号!我该如何处理?
【解决方案2】:

可以使用这样的东西。

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
}

【讨论】:

    【解决方案3】:

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

    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 对象的数组(假设您在创建字典之前对 FavoritableContact 的大数组进行了排序)。

    如果您想将其用作表格视图的数据源,您可以将节数设为所有可能的姓氏首字母。对于每个部分中的行数,您返回键的数组计数,如下所示:

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
        let letterForSection = letterForSection() // Custom method to get the section of the letter
        return contactsDict[letterForSection].count
    }
    

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

    【讨论】:

    • 我正在关注 youtube 上的视频来执行此操作。我刚刚在我的代码中添加了一些东西,我将创建一个新帖子!谢谢你的信息。我将在此处粘贴新帖子。谢啦。我已经在这工作了至少 5 个小时……我是一名新程序员。干杯!
    • 已经有 Dictionary(grouping:by:) 可以完成您在该循环中的操作
    • @Alexander 我在您发布此内容的同时更新了我的答案!早上才知道这个方法,超级好用。
    【解决方案4】:

    伙计,所有这些答案都让这件事变得过于复杂。您所需要的只是以下内容:

    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) }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-19
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 2012-04-09
      • 1970-01-01
      • 2021-07-31
      相关资源
      最近更新 更多