按字典中的NSDates排序字典数组

时间:2015-04-05 09:16:38

标签: xcode swift nsarray nsdate nsdictionary

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

我已经阅读了类似的问题,但他们是客观的C.我有一种感觉NSSortDescriptor是一种有用的方法,但我不确定如何在这种情况下使用它。

任何帮助都会很棒,

由于

1 个答案:

答案 0 :(得分:5)

如果您使用Swift编写,您可能会发现使用Swift数组类型([ContainedType])比使用NSArray更容易。除此之外,排序Swift数组比使用NSSortDescriptor等更简单。

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

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

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

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

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

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

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

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],所以你需要转换类型:

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

但是那样说,你可能在这一点上想要把你的数据存储起来不是作为一个东西的字典,而是作为一个合适的数据结构:

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作为比较的一部分进行转换。一些示例代码:

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,然后比较结果。

注意,这使用flatMap - 这是因为dateFromString本身返回一个可选项,并且您不需要可选 - 可选,因此您需要展平结果。

这是一个很大的缺点,就是没有检测到无效日期。如果你在那里有一个错误格式的日期(例如,错误顺序的月份和日期),dateFromString将返回nil并且它将被排序到数组的开头。< / p>

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