1

So if have an array of ToDos and the Todo objects have the properties due(Bool) which has the info if the ToDo has a due date; dueDate(Date) which is an optional so if due is true dueDate != nil, if due is false dueDate = nil; creationDate(Date): Date of Todo creation. Furthermore there is a property isChecked(Bool) which gives answer, if the ToDo is done or not. Now I want to sort the array of ToDos in this order:

  1. isChecked = false, closest dueDate
  2. isChecked = false, dueDate = nil, closest creationDate
  3. isChecked true, closest creationDate

How can I get this array sorted after the order above with the optional property of dueDate?

Timothy
  • 27
  • 4
  • 1
    Is the question about how to sort the objects or how to handle an optional Date when sorting? And did you try something yourself to solve this? – Joakim Danielson May 10 '22 at 20:26
  • Is is mostly about how to handle an optional and sort the objects with a value for the optional First with descending order – Timothy May 10 '22 at 21:28

1 Answers1

1

If I understand you properly, you have this kind of structure:

struct Item {
   let isChecked: Bool
   let creationDate: Date
   let dueDate: Date?
}

and I think by "closest" you mean that you want the items sorted by being close to a specific Date.

This could be done in the following manner. Let's define a helper method first:

extension Item {
   func getOrderingClosestTo(_ date: Date) -> (Int, Int, TimeInterval) {
      return (
         // items that are not checked are "smaller", they will be first
        isChecked ? 1 : 0,
        // items with dueDate are smaller, they will be first
        dueDate != nil ? 0 : 1,
        // items closer to "date" will be smaller
        abs((dueDate ?? creationDate).timeIntervalSince(date)) 
      ) 
   }
}

Then you can call:

let myDate: Date = ...
let items: [Item] = ...

let sortedItems = items.sorted { $0.getOrderingClosestTo(myDate) < $1.getOrderingClosestTo(myDate) }
Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • Wow thank you for the fast reply. It mostly works fine. Just when the Due Date for example was yesterday than the Todo is sorted last but should be at the top and the ToDo with isChecked = true seem not to be sorted correctly: first item from isChecked with date of today should be before second item with creationDate of yesterday. I hope thats understandable. I will try to retrace your solution :D – Timothy May 10 '22 at 21:15
  • @Timothy The first one is probably due to the `abs` I have used there - it doesn't see a difference between yesterday and tomorrow, it just takes the closest. I cannot test more without actual data. – Sulthan May 10 '22 at 21:28