按字典中的 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
并且它会在开始时排序数组。
另一个缺点是它变得非常低效。在进行这种处理之前,最好将数据转换为更结构化的形式(例如 struct
和 NSDate
类型的成员变量)。
我正在创建一个包含单独 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
并且它会在开始时排序数组。
另一个缺点是它变得非常低效。在进行这种处理之前,最好将数据转换为更结构化的形式(例如 struct
和 NSDate
类型的成员变量)。