Search code examples
swiftuiios15

Sorting Filtered Data by Date


I have some swiftUI logic that display entries by date and only displays the date if there is a change in date. It works great, thanks to: Display Entry Date with Change in Orientation. The one problem I have is displaying entries by order of date. For example, say someone enters some data that they forgot to enter 3 weeks ago. (My logic allows date entry with any date in the past.) This logic won't place the entry ahead of the entries posted in the last week.

Normally I could do a sort like this:

filteredArray = wdArray.sorted { (user1, user2) -> Bool in
            return user1.points > user2.points
        }

or 

filteredArray = wdArray.sorted(by: {$0.points < $1.points})

Here is the start of my class

class Withdrawal: ObservableObject {

    @Published var wdArray: [WdModel] {
        didSet {
            // save withdrawal entries
                if let encoded = try? JSONEncoder().encode(wdArray) { // save withdrawal entries
                UserDefaults.standard.set(encoded, forKey: "wdBank")
            }
        }
    }

Here is the logic that filters the entries by date (no sorting).

// creates a list of unique date entries
    // (goes through all elements, saves them in a set, checks if already in set)
    var uniqueBankDates: [String] {
        var seen: Set<String> = []
        return wdvm.wdArray.filter { seen.insert($0.wdDate.formatted(date: .abbreviated, time: .omitted)).inserted }
            .map {$0.wdDate.formatted(date: .abbreviated, time: .omitted) }
    }

So the bottom line is that I need help modifying uniqueBankDates to filter AND sort the sets by date (oldest entries first). I would appreciate any help on this. Thanks


Solution

  • You don't need to "save" the elements in a set - you can just:

    • turn the array into a Set by simply using Set(array), this will remove the duplicates
    • turn the Set back to an array by using Array(yourSetHere)
    • sort it
    • turn the array of dates into an array of strings

    Here's what uniqueBankDates should look like (WdModel shall be conform to Hashable):

        var uniqueBankDates: [String] {
            Array(Set(wdvm.wdArray))                // This will remove duplicates, but WdModel needs to be Hashable
                .sorted { $0.wdDate < $1.wdDate }   // Compare dates
                .compactMap {
                    $0.wdDate.formatted(date: .abbreviated, time: .omitted)    // Return an array of formatted the dates
                }
        }