【问题标题】:Sort Array of Dictionaries by NSDates within the Dictionaries按字典中的 NSDates 对字典数组进行排序
【发布时间】:2015-04-05 09:16:37
【问题描述】:

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

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

任何帮助都会很棒,

谢谢

【问题讨论】:

    标签: xcode swift nsarray nsdate nsdictionary


    【解决方案1】:

    如果您使用 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 { $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,并且它会被排序到数组的开头。

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

    【讨论】:

    • 非常感谢您的广泛回答!但是,我确实有一个问题 - 数组中包含的所有字典都是 。这意味着当我的 NSDate 到达排序部分时,它是一个字符串。通过警告引起我的注意 - 从 NSString 到 NSDate 的转换总是失败(除非格式正确)。我该如何解决这个问题?
    猜你喜欢
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-17
    • 2020-11-02
    • 1970-01-01
    • 2011-02-22
    相关资源
    最近更新 更多