iOS Swift:将数组排序为多维数组

Posted

技术标签:

【中文标题】iOS Swift:将数组排序为多维数组【英文标题】:iOS Swift: Sort array into multidimensional array 【发布时间】:2015-03-01 00:40:04 【问题描述】:

我有一个 CKRecords 数组。每条记录都有startTimeName 以及其他值。我想做的是首先按唯一的startTime 对记录进行排序,然后在每个 startTime 中按唯一的Name 排序。

最终结果将是一个看起来像这样的数组(我认为):records = [Date: [Name: [CKRecord]]]

这是我现在拥有的:

func buildIndex(records: [CKRecord]) -> [[CKRecord]] 
var dates = [NSDate]()
var result = [[CKRecord]]()

for record in records 
    var date = record.objectForKey("startTime") as! NSDate

    if !contains(dates, date) 
        dates.append(date)
    


for date in dates 
    var recordForDate = [CKRecord]()

    for (index, exercise) in enumerate(exercises) 
        let created = exercise.objectForKey("startTime") as! NSDate

        if date == created 
            let record = exercises[index] as CKRecord
            recordForDate.append(record)
        
    
    result.append(recordForDate)


return result


let records = self.buildIndex(data)

【问题讨论】:

【参考方案1】:

为什么不使用sorted?像这样。

// A simplified version of your `CKRecord` just for demonstration
struct Record 
    let time: NSDate
    let name: String


let records = [
    Record(time: NSDate(timeIntervalSince1970: 1), name: "a"),
    Record(time: NSDate(timeIntervalSince1970: 2), name: "b"),
    Record(time: NSDate(timeIntervalSince1970: 1), name: "c"),
    Record(time: NSDate(timeIntervalSince1970: 3), name: "d"),
    Record(time: NSDate(timeIntervalSince1970: 3), name: "e"),
    Record(time: NSDate(timeIntervalSince1970: 2), name: "f"),
]

func buildIndex(records: [Record]) -> [[Record]] 
    var g = [NSDate: [Record]]()
    for e in records 
        if (g[e.time] == nil) 
            g[e.time] = []
        
        g[e.time]!.append(e) // grouping by `time`
    
    return sorted(g.keys)  (a: NSDate, b: NSDate) in
        a.compare(b) == .OrderedAscending // sorting the outer array by 'time'
    
    // sorting the inner arrays by `name`
    .map  sorted(g[$0]!)  $0.name < $1.name   


println(buildIndex(records))

【讨论】:

你能把g[e.time] = (g[e.time] ?? []) + [e]写得不那么简洁吗?试图理解那条线。 只是在g字典中的数组中追加一个元素。 我收到了.map sorted(g[$0]!) $0.name &lt; $1.name 行的Expected type 编译器错误。知道这意味着什么吗? @colindunnn 我刚刚再次测试了上面的代码,但我看不到那个错误。你修改代码了吗?如果是这样,请告诉我修改后的版本。我也许可以帮助你。 @colindunnn 你的意思是这样的吗? gist.github.com/hisui/f4aea3d1d6f5881eebd2(但是,在这种情况下,buildIndex 的输出必须是 CKRecord.. 的 3 维数组)【参考方案2】:

首先,您实际上并不是在尝试对数组进行排序,而是在尝试对字典进行排序,该字典不是为按顺序迭代而构建的。事实上,即使你先对数组进行排序,然后像这样构建字典:

var sortedRecords = [NSDate: [String: CKRecord]]()
records.sort  return $0.date.timeIntervalSinceDate($1.date) < 0 

for record in records 
    if sortedRecords[record.date] != nil 
        sortedRecords[record.date] = [String: CKRecord]()
    

    sortedRecords[record.date]![record.name] = record

当您将来对其进行迭代时,无法保证该顺序。也就是说,字典本质上是一个查找表,并且可以在 O(log n) 时间内访问元素。您真正想要做的是要么删除字典,而是使用 [CKRecord] 数组,然后像这样排序:

records.sort  $0.date.timeIntervalSinceDate($1.date) == 0 ? $0.name < $1.name : $0.date.timeIntervalSinceDate($1.date) < 0 

或者,根据您的最终目标,遍历一系列日期,边走边从字典中提取条目。

【讨论】:

感谢您的解释。我试图在两个地方显示记录。首先作为表格视图(我需要所有记录),然后在详细视图中(我只需要记录的子集)。我对分组的目标是更容易地只访问我需要的信息。但也许有更好的方法。 使用适合特定问题的数据结构。对于 tableView,您需要将记录保存在排序数组中。对于详细视图,构造一个将数组转换为字典并返回它的 getter,例如:lazy var recordsByDate: [NSDate: [String:CKRecord]] ... Dictionary Buildng Method Goes Here ... 【参考方案3】:

您可以执行 CloudKit 查询并确保以正确的排序顺序返回数组,如下所示:

    query.sortDescriptors = [NSSortDescriptor(key: "startTime", ascending: true), NSSortDescriptor(key: "Name", ascending: true)]

然后,如果您转到详细视图,您可以使用过滤器来获取当天的记录,如下所示:

   var details = records.filter  (%0.objectForKey("startTime") As! NSDate) == selectedDate 

【讨论】:

以上是关于iOS Swift:将数组排序为多维数组的主要内容,如果未能解决你的问题,请参考以下文章

如何将平面数组排序为多维树

按子项的值对多维数组进行排序

将多维数组保存到存储

php多维数组排序

JavaScript:自动对可变多维数组进行对角排序

js多维数组转一维数组+数组去重+排序