设置不删除重复日期

Set not Removing Duplicate Dates

我有一个显示按日期排序的条目的结构。对于同一日期的所有条目,日期只显示一次。我遇到的问题是 Set 没有删除重复的日期。如果我有两个具有相同日期的条目,我在视图中有两个块,每个块中都有相同的条目。请参阅我的原始 post 如果我输入具有相同日期的多个条目,uniqueDates(使用调试器查找)会显示具有相同日期的相同数量的元素。

我的理论是 Array(Set(wdvm.wdArray)) 在完整的未格式化日期上排序,其中包括每个元素中的时间或其他变量。因此它认为所有日期都是唯一的。有没有使用格式化日期进行排序的方法?

struct WithdrawalView: View {

    @StateObject var wdvm = Withdrawal()

    var uniqueDates: [String] {

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


    // filters entries for the given date
    func bankEntries(for date: String) -> [WdModel] {
        return wdvm.wdArray.filter { [=10=].wdDate.formatted(date: .abbreviated, time: .omitted) == date }
    }

    var body: some View {

        GeometryReader { g in


            VStack (alignment: .leading) {
                
                WDTitleView(g: g)
                List {
                    if wdvm.wdArray.isEmpty {

                        NoItemsView()

                    } else {

                        // outer ForEach with unique dates
                        ForEach(uniqueDates, id: \.self) { dateItem in  // change this to sort by date
                            Section {
                                // inner ForEach with items of this date
                                ForEach(bankEntries(for: dateItem)) { item in

                                    wdRow(g: g, item: item)

                                }
                            } header: {
                                Text("\(dateItem)")
                            }
                        }.onDelete(perform: deleteItem)
                    }
                }
                .navigationBarTitle("Bank Withdrawals", displayMode: .inline)
     

下面是本模块使用的class

struct WdModel: Codable, Identifiable, Hashable {

    var id = UUID()
    var wdDate: Date        // bank withdrawal date
    var wdCode: String      // bank withdrawal currency country 3-digit code
    var wdBank: String      // bank withdrawal bank
    var wdAmtL: Double      // bank withdrawal amount in local currency
    var wdAmtH: Double      // bank withdrawal amount in home currency
    var wdCity: String
    var wdState: String
    var wdCountry: String
}


class Withdrawal: ObservableObject {

    @AppStorage(StorageKeys.wdTotal.rawValue) var withdrawalTotal: Double = 0.0

    @Published var wdArray: [WdModel]
       
    init() {

        if let wdArray = UserDefaults.standard.data(forKey: StorageKeys.wdBank.rawValue) {   
            if let decoded = try? JSONDecoder().decode([WdModel].self, from: wdArray) {
                self.wdArray = decoded
                return
            }
        }

        self.wdArray = []


    // save new withdrawal data    
func addNewWithdrawal(wdDate: Date, wdCode: String, wdBank: String, wdAmtL: Double, wdAmtH: Double, wdCity: String, wdState: String, wdCountry: String) -> () {

        self.withdrawalTotal +=  wdAmtH

        let item = WdModel(wdDate: wdDate, wdCode: wdCode, wdBank: wdBank, wdAmtL: wdAmtL, wdAmtH: wdAmtH, wdCity: wdCity, wdState: wdState, wdCountry: wdCountry)
        
        wdArray.append(item)

        if let encoded = try? JSONEncoder().encode(wdArray) { // save withdrawal entries
            UserDefaults.standard.set(encoded, forKey: StorageKeys.wdBank.rawValue)
        }
    }
}

我试图在一个日期下显示同一日期的所有条目。这个例子显示了我想要的但不是日期和条目的 3 个副本。

Set删除重复的日期,请尝试这样的操作:

var uniqueDates: [String] {
    Array(Set(wdvm.wdArray.map { [=10=].wdDate }))
        .sorted { [=10=] <  }
        .compactMap {
            [=10=].formatted(date: .abbreviated, time: .omitted)
        }
}

编辑-3:

display给定日期的唯一bankEntries,基于日期的日、月和年(不是秒等...):

struct ContentView: View {
    @State var wdArray = [WdModel]()
    
    let frmt: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM dd, yyyy"
        return formatter
    }()
    
    func bankEntries(for date: String) -> [WdModel] {
        return wdArray.filter { frmt.string(from: [=11=].wdDate) == date }
    }

    var uniqueDates: [String] {
        Array(Set(wdArray.map { frmt.string(from: [=11=].wdDate) }))
            .sorted { frmt.date(from: [=11=]) ?? Date() < frmt.date(from: ) ?? Date() }
            .compactMap { [=11=] }
    }

    var body: some View {
        List {
            // outer ForEach with unique dates
            ForEach(uniqueDates, id: \.self) { dateItem in  // change this to sort by date
                Section {
                    // inner ForEach with items of this date
                    ForEach(bankEntries(for: dateItem)) { item in
                      //  wdRow(g: g, item: item)
                        HStack {
                            Text(item.wdDate.formatted(date: .abbreviated, time: .omitted))
                            Text(item.wdCode).foregroundColor(.red)
                        }
                    }
                } header: {
                    Text("\(dateItem)")
                }
            }
        }
        .onAppear {
            let today = Date()  // <-- here
            let otherDate = Date(timeIntervalSince1970: 345678)
            
            wdArray = [
                WdModel(wdDate: today, wdCode: "EUR", wdBank: "Bank of Innsbruck", wdAmtL: 4575, wdAmtH: 1625, wdCity: "Innsbruck", wdState: " Tyrol", wdCountry: "Aus"),
                
                WdModel(wdDate: otherDate, wdCode: "CHF", wdBank: "Bank of Interlaken", wdAmtL: 6590, wdAmtH: 2305, wdCity: "Interlaken", wdState: "Bernese Oberland ", wdCountry: "CHF"),
                
                WdModel(wdDate: today, wdCode: "USD", wdBank: "Bank X", wdAmtL: 1200, wdAmtH: 3275, wdCity: "Las Vegas", wdState: "NV", wdCountry: "USA")
            ]
        }
    }
}