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

Mat*_*att 0 xcode nsdictionary nsdate nsarray swift

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

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

任何帮助都会很棒,

谢谢

Air*_*ity 5

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

NSDates可以使用.compare如下比较:

let d1 = NSDate()
let d2 = NSDate()
d1.compare(d2) == .OrderedAscending
Run Code Online (Sandbox Code Playgroud)

但您可能更喜欢它们来实现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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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"]
}
Run Code Online (Sandbox Code Playgroud)

除了...实际上[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)
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

posts.sorted { $0.timestamp < $1.timestamp }
Run Code Online (Sandbox Code Playgroud)

编辑:你的评论提到你实际上有一个类型的字典[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)
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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