1

I have an array with a property of string that resembles a date (yyyy-MM-dd) and another property of string that resembles a time (HH:mm).

I am trying to sort the array by date and then time in 1 sweep.

Example:

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

and i want to achieve

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.

How can i achieve this using Swift?

Thank you so much for your time!

2
  • I think you can convert your date and time to "Unix Timestamp" then use sort method. Commented Nov 19, 2019 at 15:37
  • See stackoverflow.com/questions/37603960/… Commented Nov 19, 2019 at 16:13

3 Answers 3

1

This answer picks up on the refinement to the question in the below comment from the OP in response to the answer from @vadian. The actual requirement is to sort football goal times provided by the API. The solution below creates a struct for this data with a calculated variable for actual goal time and then sorts by that.

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

I tested this as below

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

and it correctly produced:

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 

There is room for improvement by not force unwrapping the Date?, although the string cleaning makes this reasonably safe, and by using a class-level static DateFormatter. But I'll leave that refinement for the implementation :-)

Sign up to request clarification or add additional context in comments.

Comments

0

First of all please name variables with starting lowercase letter (array)

You can simply sort the array by concatenating the strings because the format yyyy-MM-dd HH:mm is sortable.

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

6 Comments

Yes, sorry, i am naming my variables starting lowecase in my code. This was just a fictive example. Ok, i got it, it makes sense what you’re saying, you a genious!! But i have another problem. Let me be more concrete, i am building a football scores app and i need to show the goals live when they happen and i use an api that gives me 3 variables, match_date, match_time and score_time. How do i sort so that i get the latest goal scored at the top of the list?
That's another question and the information might be more concrete but not concrete enough. What does score_time contain? Another string or an Int representing the minute when the goal was scored relative to the match time
It is a string that contains the minute when the goal was scored like: “87” or “23” or “90+2”
This isn't great. String sorts for date/time are flaky, because changing the storage format would quietly break the sorting (and only for some data). Also, it's slower than just using time addition operations, which could hurt depending on the number of element.
@Alexander Actually changing the storage format would break any code.
|
0

You could append the date and time strings, because the largest time interval (year) is on the left, and smallest (minute) is on the right. Sorting by standard lexicographical means will put the “largest” date / time combination first.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.