简体   繁体   English

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

[英]iOS Swift: Sort array into multidimensional array

I have an array of CKRecords. 我有一个CKRecords数组。 Each record has startTime and a Name , among other values. 每个记录都有startTimeName以及其他值。 What I would like to do is sort the records first by unique startTime and then within each startTime sort by unique Name . 我想做的是首先按唯一的startTime对记录进行排序,然后在每个startTime中按唯一的Name排序。

The end result would be an array that looks like this (I think): records = [Date: [Name: [CKRecord]]] 最终结果将是一个看起来像这样的数组(我认为): records = [Date: [Name: [CKRecord]]]

Here is what I have right now: 这是我现在所拥有的:

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)

Why not use sorted ? 为什么不使用sorted Like this. 像这样。

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

First of all, you're not really trying to sort an array here, you're trying to order a dictionary, which isn't built to be iterated over sequentially. 首先,您并不是真正要在此处对数组进行排序,而是要订购一个字典,该字典的构建并不是要顺序地进行迭代。 In fact even if you do sort the array first and then build the dictionary like this: 实际上,即使您先对数组进行排序,然后再像这样构建字典:

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
}

The order isn't guaranteed when you iterate over it in the future. 将来当您遍历该顺序时,不能保证该顺序。 That said, a dictionary is essentially a look up table, and elements can be accessed in O(log n) time. 也就是说,字典本质上是一个查找表,可以在O(log n)时间访问元素。 What you'll really want to do is either drop the dictionary is favor of an array of [CKRecord] and then sort like this: 您真正想要做的是要么删除字典,而使用[CKRecord]数组,然后进行如下排序:

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

Or, depending on what your end goal is, iterate across a range of dates, plucking the entries from the dictionary as you go. 或者,根据您的最终目标是,在多个日期范围内进行迭代,并随身携带字典中的条目。

You could execute the CloudKit query and make sure that you get the array returned in the correct sort order like this: 您可以执行CloudKit查询,并确保以正确的排序顺序返回数组,如下所示:

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

And then if you go to the detail view, you could use the filter for getting the records for that day like this: 然后,如果转到详细信息视图,则可以使用过滤器来获取当天的记录,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM