按字典中的 NSDates 对字典数组进行排序

Sort Array of Dictionaries by NSDates within the Dictionaries

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

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

任何帮助都会很棒,

谢谢

如果您使用 Swift 编写,您可能会发现使用 Swift 数组类型 ([ContainedType]) 比 NSArray 更容易。除其他事项外,排序 Swift 数组比必须使用 NSSortDescriptor 等更直接

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

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 { [=15=].timestamp < .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 本身 return 是一个可选的,而你不想要一个可选的可选的,所以你需要展平结果.

最大的缺点是无法检测到无效日期。如果你在那里的日期格式不正确(比如,月份和日期的顺序错误),dateFromString 将 return nil 并且它会在开始时排序数组。

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