【问题标题】:Sort NSArray of date strings or objects对日期字符串或对象的 NSArray 进行排序
【发布时间】:2010-11-11 02:15:18
【问题描述】:

我有一个 NSArray,其中包含日期字符串 (即 NSString),如下所示:“Thu, 21 May 09 19:10:09 -0700”

我需要按日期对NSArray 进行排序。我考虑过先将日期字符串转换为NSDate 对象,但在如何按NSDate 对象排序时卡住了。

谢谢。

【问题讨论】:

  • 重新标记,因为这与 Foundation 框架有关,而不是特定于 iPhone。

标签: objective-c cocoa sorting nsarray nsdate


【解决方案1】:

拥有NSDate 后,您可以使用initWithKey:ascending: 创建NSSortDescriptor,然后使用sortedArrayUsingDescriptors: 进行排序。

【讨论】:

  • 这种方法可行,但使用 -sortedArrayUsingSelector: 稍微简单一些,不需要创建额外的对象。
  • 预编辑,问题提到了“一个'日期'键”,所以我认为这实际上是一组对象/字典,其中一个日期为一个字段,而不是一组原始日期。在这种情况下 sortedArrayUsingSelector: 更复杂,因为它需要编写自定义排序例程来进行查找。
  • 是的,很抱歉有任何混淆——我清理了那个引用,因为他只是说他用“日期”键存储他的数组,我意识到这只会让问题变得更加混乱。考虑到更复杂的数据结构,您对相对复杂性的看法绝对正确。
【解决方案2】:

您可以使用sortedArrayUsingFunction:context:。这是一个示例:

NSComparisonResult dateSort(NSString *s1, NSString *s2, void *context) {
    NSDate *d1 = [NSDate dateWithString:s1];
    NSDate *d2 = [NSDate dateWithString:s2];
    return [d1 compare:d2];
}

NSArray *sorted = [unsorted sortedArrayUsingFunction:dateSort context:nil];

使用NSMutableArray 时,您可以改用sortArrayUsingFunction:context:

【讨论】:

  • 这是个坏主意——比较函数应该很快,并且不应该为每次比较都从字符串创建 NSDate 对象。如果您已经在使用 -[NSDate compare:],只需将日期存储在数组中并直接使用 -sortedArrayUsingSelector:。
  • 我认为如果您正在对已经具有 NSDate 字段的对象进行排序,这是一个很好的解决方案。没有?
  • 如果数组已经包含NSDate对象,你可以使用我上面的答案,甚至使用10.6中添加的-[NSMutableArray sortUsingComparator:]
  • 如果您正在使用一个字典数组,其中有一个作为 NSString 的日期键值对象以及一些其他键值对象,那么这个解决方案是迄今为止最好的。只需要在 dateSort 函数中进行一些修改。竖起大拇指! :)
【解决方案3】:

将日期作为 NSDate 对象存储在 NS(Mutable)Array 中,然后使用 -[NSArray sortedArrayUsingSelector:-[NSMutableArray sortUsingSelector:] 并将 @selector(compare:) 作为参数传递。 -[NSDate compare:] 方法将为您按升序排列日期。这比创建NSSortDescriptor 简单,也比编写自己的比较函数简单得多。 (NSDate 对象知道如何相互比较,至少与我们希望使用自定义代码完成的效率一样。)

【讨论】:

  • 不清楚最初的问题是询问对日期数组进行排序,还是对具有日期字段的对象数组进行排序。如果是前者,这是最简单的方法,但如果是后者,NSSortDescriptor 是要走的路。
  • @smorgan NSSortDescriptor 如何处理零日期?
  • 感谢您的帮助,我认为我们应该在 Apple Docs 中阅读更多内容,但它似乎很无聊,直到您使用它。
  • 您能以 sn-p 代码为例吗?提前致谢。
【解决方案4】:

如果我有一个NSMutableArray 的对象,其字段“beginDate”类型为NSDate,我正在使用NSSortDescriptor,如下所示:

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE];
[myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

【讨论】:

  • 我知道已经过去了很多时间(当先前的答案被接受时,可能还没有 NSSortDescriptor),但是对于将来的使用,这应该是正确的答案。
  • 这是一个很棒的解决方案。用几行代码解决了我的问题。谢谢@vinzenzweber
  • 真的......我真的很震惊这个第一次运行!我认为 initWithKey 是为定义了键的字典保留的,但是您需要做的就是引用对象数组中的属性?让光芒照耀vinzenzweberskavitchski!!
  • NSSortDescriptor 自 2003 年底 OS X 10.3 以来一直存在。这是一个稍微不同的场景,其中日期是另一个对象中的一个字段。使用更现代的 API,您不妨使用 -[NSMutableArray sortUsingComparator:] (10.6+) 并传递一个块,该块返回在两个字段上调用 ​​-compare: 的结果。它可能比在每个对象上调用 -valueForKey: 更快。您甚至可以使用-sortWithOptions:usingComparator: 并传递选项以同时进行排序。
  • 上面的 NSSortDescriptor 如何处理 nil 日期?如果需要,我们是否需要告诉描述符如何处理它们,如何处理?
【解决方案5】:

您可以使用块进行就地排序:

sortedDatesArray = [[unsortedDatesArray sortedArrayUsingComparator: ^(id a, id b) {
    NSDate *d1 = [NSDate dateWithString: s1];
    NSDate *d2 = [NSDate dateWithString: s2];
    return [d1 compare: d2];
}];

我建议您在排序之前将所有字符串转换为日期,以免转换次数超过日期项。任何排序算法都会为您提供比数组中的项目数更多的字符串到日期转换(有时更多)

关于块排序的更多信息:http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html

【讨论】:

  • 这是@notoop 提出的相同次优想法的变体。无论如何,首先转换为 NSDate 绝对是要走的路。
  • 他基本上只是把我的答案和@notoop 的答案放在一起......如果你问我的话,完全没有必要重复发布这些......
  • 这比将日期字符串解析为 NSDate 数组然后对 NSDate 数组进行排序要慢得多,因为会有 2 * (n - 1) 次额外的字符串解析。解析字符串通常是 CPU 上的繁重工作。
【解决方案6】:

你也可以使用类似下面的东西:

//Sort the array of items by  date
    [self.items sortUsingComparator:^NSComparisonResult(id obj1, id obj2){
        return [obj2.date compare:obj1.date];
    }];

但这确实假设日期存储为NSDate 而不是NString,这应该没有问题。最好,我建议还以原始格式存储数据。在这种情况下更容易操作。

【讨论】:

    【解决方案7】:

    改一下

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"beginDate" ascending:TRUE];
    [myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    [sortDescriptor release];
    

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Date" ascending:TRUE];
    [myMutableArray sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    [sortDescriptor release];
    

    只需更改 KEY:它必须始终为 Date

    【讨论】:

      【解决方案8】:

      在我的情况下它的作用如下:

       NSArray *aUnsorted = [dataToDb allKeys];
          NSArray *arrKeys = [aUnsorted sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
              NSDateFormatter *df = [[NSDateFormatter alloc] init];
              [df setDateFormat:@"dd-MM-yyyy"];
              NSDate *d1 = [df dateFromString:(NSString*) obj1];
              NSDate *d2 = [df dateFromString:(NSString*) obj2];
              返回[d1比较:d2];
          }];

      我有一本字典,其中所有键的日期格式为 dd-MM-yyyy。 allKeys 返回未排序的字典键,我想按时间顺序呈现数据。

      【讨论】:

        【解决方案9】:

        Swift 3.0

        myMutableArray = myMutableArray.sorted(by: { $0.date.compare($1.date) == ComparisonResult.orderedAscending })
        

        【讨论】:

          猜你喜欢
          • 2014-02-22
          • 1970-01-01
          • 1970-01-01
          • 2022-01-12
          • 1970-01-01
          • 2015-08-21
          • 1970-01-01
          • 2021-09-06
          • 2018-08-28
          相关资源
          最近更新 更多