Sort Array of Dictionaries by NSDates within the Dictionaries

孤者浪人 提交于 2020-01-17 04:23:45

问题


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.

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.

Any help would be great,

Thanks


回答1:


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 can be compared using .compare like so:

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

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"]
}

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 }

EDIT: 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)
}

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

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.

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.

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.



来源:https://stackoverflow.com/questions/29455824/sort-array-of-dictionaries-by-nsdates-within-the-dictionaries

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!