【问题标题】:Swift - Sort array by date and time in one goSwift - 一次性按日期和时间对数组进行排序
【发布时间】:2019-11-19 15:26:55
【问题描述】:

我有一个数组,它的字符串属性类似于日期 (yyyy-MM-dd) 和字符串的另一个属性类似于时间 (HH:mm)。

我正在尝试按日期对数组进行排序,然后在 1 次扫描中按时间排序。

例子:

Array[0].date = 2019-11-18
Array[0].time = 19:00
Array[1].date = 2019-11-18
Array[1].time = 22:00
Array[2].date = 2019-10-14
Array[2].time = 16:00
Array[3].date = 2019-11-16
Array[3].time = 13:00
Array[4].date = 2019-11-16
Array[4].time = 14:00

我想实现

Array[0].date = 2019-11-18
Array[0].time = 22:00
Array[1].date = 2019-11-18
Array[1].time = 19:00
Array[2].date = 2019-10-16
Array[2].time = 14:00
Array[3].date = 2019-10-16
Array[3].time = 13:00
Array[4].date = 2019-11-14
Array[4].time = 16:00.

如何使用 Swift 实现这一点?

非常感谢您的宝贵时间!

【问题讨论】:

标签: arrays swift sorting


【解决方案1】:

此答案是对 OP 以下评论中问题的改进,以回应@vadian 的回答。实际需求是对 API 提供的足球进球时间进行排序。下面的解决方案使用实际目标时间的计算变量为此数据创建一个结构,然后按此排序。

struct Goal{
   let matchDate: String
   let matchTime: String
   let goalTime: String

   var timeOfGoal: Date {
      let goalComponents = goalTime.components(separatedBy: "+").map{$0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines.union(CharacterSet.decimalDigits.inverted))}
      let goalSeconds = TimeInterval(60 * goalComponents.compactMap({Int($0)}).reduce(0, +))
      let dateFormatter = DateFormatter()
      dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
      let startTime = dateFormatter.date(from: matchDate + " " + matchTime)!
      return startTime.addingTimeInterval(goalSeconds)
   }
}

我对此进行了如下测试

let goals = [
   Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90 +7"),
   Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "22"),
   Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "99"),
   Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "45 + 3"),
   Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "45+6"),
   Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90+6"),
   Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "35"),
   Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "85"),
   Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90"),
   Goal(matchDate: "2019-11-18", matchTime: "22:00", goalTime: "90+ 8"),
   Goal(matchDate: "2019-11-18", matchTime: "19:00", goalTime: "44")]

let ordered = goals.sorted{$0.timeOfGoal > $1.timeOfGoal}

ordered.forEach{print("\($0.matchDate) - \($0.matchTime) - \($0.goalTime) ")}

它正确地产生了:

2019-11-18 - 22:00 - 99 
2019-11-18 - 22:00 - 90+ 8 
2019-11-18 - 22:00 - 90 +7 
2019-11-18 - 22:00 - 90+6 
2019-11-18 - 22:00 - 90 
2019-11-18 - 22:00 - 85 
2019-11-18 - 22:00 - 35 
2019-11-18 - 19:00 - 45+6 
2019-11-18 - 19:00 - 45 + 3 
2019-11-18 - 19:00 - 44 
2019-11-18 - 19:00 - 22 

不强制解包Date? 有改进的余地,尽管字符串清理使这相当安全,并且通过使用类级静态 DateFormatter。但是我会把这个改进留给实现:-)

【讨论】:

    【解决方案2】:

    您可以附加日期和时间字符串,因为最大的时间间隔(年)在左侧,最小的(分钟)在右侧。按标准字典顺序排序会将“最大”日期/时间组合放在首位。

    let sortedArray = myArray.sorted(by: { ($0.date + $0.time) > ($1.date + $1.time) })
    

    【讨论】:

      【解决方案3】:

      首先请以小写字母(array)命名变量

      您可以通过连接字符串来简单地对数组进行排序,因为yyyy-MM-dd HH:mm 格式是可排序的。

      array.sort{"\($0.date) \($0.time)" > "\($1.date) \($1.time)"}
      

      【讨论】:

      • 是的,对不起,我在我的代码中以小写字母开头命名我的变量。这只是一个虚构的例子。好吧,我明白了,你说的很有道理,你是个天才!!但我还有另一个问题。让我更具体一点,我正在构建一个足球比分应用程序,我需要在目标发生时实时显示目标,我使用一个 api,它给了我 3 个变量,match_date、match_time 和 score_time。我如何排序,以便我得到最新的进球在列表的顶部?
      • 这是另一个问题,信息可能更具体,但不够具体。 score_time 包含什么?另一个字符串或 Int 表示相对于比赛时间进球的分钟
      • 这是一个字符串,包含进球时的分钟,例如:“87”或“23”或“90+2”
      • 这不是很好。日期/时间的字符串排序是不稳定的,因为更改存储格式会悄悄地破坏排序(并且仅适用于某些数据)。此外,它比仅使用时间加法操作要慢,这可能会受到元素数量的影响。
      • @Alexander 实际上更改存储格式会破坏任何代码。
      猜你喜欢
      • 2021-02-23
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 1970-01-01
      • 2020-02-29
      • 2017-06-13
      • 1970-01-01
      • 2022-01-14
      相关资源
      最近更新 更多