按字典中的 NSDates 对字典数组进行排序 [英] Sort Array of Dictionaries by NSDates within the Dictionaries

查看:56
本文介绍了按字典中的 NSDates 对字典数组进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个包含单独帖子的应用程序(类似于 Instagram).每个帖子都是一个位于一个大数组中的字典.在每个字典中,它们是一个 NSDate,我想按照从最新到最旧的顺序对字典进行排序.

I am creating an application with separate posts in it (similar to Instagram). Each post is a dictionary located in one big array. Within each dictionary their is an NSDate which I would like to sort the dictionaries by in order from newest to oldest.

我读过类似的问题,但它们是目标 C.我感觉 NSSortDescriptor 是一种有用的方法,但我不确定如何在这种情况下使用它.

I have read similar questions but they are in objective C. I have a feeling NSSortDescriptor be a helpful method but am unsure on how to use it in this situation.

任何帮助都会很棒,

谢谢

推荐答案

如果您使用 Swift 编写代码,您可能会发现使用 Swift 数组类型 ([ContainedType]) 会更容易比 NSArray.除此之外,对 Swift 数组进行排序比必须使用 NSSortDescriptor 等更直接.

If you’re writing in Swift, you’ll probably find it easier to use the Swift array type ([ContainedType]) than NSArray. Amongst other things, sorting Swift arrays is more straightforward than having to use NSSortDescriptor etc.

NSDates 可以使用 .compare 进行比较,如下所示:

NSDates can be compared using .compare like so:

let d1 = NSDate()
let d2 = NSDate()
d1.compare(d2) == .OrderedAscending

但您可能更喜欢它们实现 Comparable 协议,可以这样做:

But you might prefer them to implement the Comparable protocol, which can be done like this:

extension NSDate: Comparable { }

public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
    return lhs.isEqualToDate(rhs)
}

public func <(lhs: NSDate, rhs: NSDate) -> Bool {
    return lhs.compare(rhs) == .OrderedAscending
}

// now you can do
d1 > d2
d1 <= d2  //etc

有了这个,你可以对日期数组进行排序:

With this, you can sort arrays of dates:

let arr = [d2, d1]
let sortedArr = arr.sorted(<) // or > for descending order

如果您有日期字典,则需要从字典中提取日期值并进行比较,但这很简单:

If you had dictionaries of dates, you would need to fetch the date value out dictionary and compare it, but that’s easy:

let dicts = [["Date":d2], ["Date":d1]]

// pass sorted a function that compares two candidates in the array
dicts.sorted { lhs, rhs in
    // even though dictionary lookups return optionals,
    // this is fine because < is defined for optionals of Comparables
    // (nil is < anything else)
    lhs["Date"] < (rhs["Date"]
}

除了……很可能你实际上没有一个 [String:NSDate] 数组——你可能在那里有一堆不同的类型,它实际上是一个 [String:AnyObject],所以需要转换类型:

Except… chances aren’t that you actually have an array of [String:NSDate] – you probably have a bunch of different types in there and its actually a [String:AnyObject], so you need to convert the type:

// dictionaries contain various different kind of values
let dicts: [[String:AnyObject]] = [["Date":d2], ["Date":d1]]

dicts.sorted { lhs, rhs in
    (lhs["Date"] as? NSDate) < (rhs["Date"] as? NSDate)
}

话虽如此,此时您可能想要考虑将数据存储为一种适当的数据结构,而不是将数据存储为字典:

But that said, you probably at this point want to think about storing your data not as a dictionary of stuff, but as a proper data structure:

struct Post {
    let timestamp: NSDate
    // and various other properties...
}

let posts: [Post] = [
    Post(timestamp: d1),
    Post(timestamp: d2)
]

posts.sorted { $0.timestamp < $1.timestamp }

您的评论提到您实际上有一个 [String:String] 类型的字典.这意味着您需要在比较之前以某种方式将字符串转换为日期.在这种情况下,您可以使用 NSDateFormatter 作为比较的一部分进行转换.一些示例代码:

your comment mentions that you actually have a dictionary of type [String:String]. This means you need to convert the strings to dates somehow before comparing them. In which case, you could use NSDateFormatter to convert as part of the comparison. Some example code:

let dicts: [[String:String]] = [["Date":"May 20 20015"], ["Date":"May 20 2014"]]
let fmt = NSDateFormatter()
fmt.dateStyle = .MediumStyle

let sortedDicts = dicts.sorted { lhs, rhs in
    lhs["Date"].flatMap(fmt.dateFromString) < rhs["Date"].flatMap(fmt.dateFromString)
}

因此,在进行比较时,取出日期字符串,然后使用格式化程序将其转换为 NSDate,然后比较结果.

So, when doing the comparison, fetch the date string out, then convert it to a NSDate using the formatter, then compare the result.

注意,这里使用了 flatMap——这是因为 dateFromString 本身返回一个可选的,而你不想要一个可选的可选,所以你需要展平结果.

Note, this uses flatMap – this is because dateFromString itself returns an optional, and you don’t want an optional-optional so you need to flatten the result.

最大的缺点是无法检测到无效日期.如果你在那里得到一个格式错误的日期(比如,月和日的顺序错误),dateFromString 将返回 nil 并且它会被排序到数组的开始.

The big downside to this is there’s no detection of invalid dates. If you got a date in there that was a bad format (say, month and day in the wrong order), dateFromString would return nil and it’d get sorted towards the start of the array.

另一个缺点是它变得非常低效.在进行此类处理之前,最好将数据转换为更结构化的形式(例如带有 NSDate 类型成员变量的 struct).

The other downside of this is it’s getting pretty horribly inefficient. You may well be better off converting your data to more structured form (e.g. a struct with an NSDate-typed member variable) before doing this kind of processing.

这篇关于按字典中的 NSDates 对字典数组进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆