0

I am attempting to remove duplicate elements of my Transaction object. The Transactions are being loaded from Firestore and displayed onto a UTableView. I tried to follow this answer [here][1] however I got an error that budgetData is not hashable. Is there a way I can remove duplicate Transactions that have the same "transId" and return an updated array of budgetdata?

  var budgetData: [Transaction] = []

func loadCatTransactions(){
    if let catId = self.categoryId{
        guard let user = Auth.auth().currentUser?.uid else { return }
        print("userFromLoadChat::\(user)")
        db.collection("users").document(user).collection("Transactions")
            .whereField("catId", isEqualTo: catId)
            .getDocuments() {
                snapshot, error in
                if let error = error {
                    print("\(error.localizedDescription)")
                } else {
                    self.budgetData.removeAll()
                    for document in snapshot!.documents {
                        let data = document.data()
                        let title = data["name"] as? String ?? ""
                        let date = data["date"] as? String ?? ""
                        let amount = data["amount"] as? Double ?? 0
                        let id = data["transId"] as? String ?? ""

                        let trans = Transaction(catId:catId,title: title, dateInfo: date, image: UIImage.groceriesIcon, amount: amount)
                        self.budgetData.append(trans)
                        DispatchQueue.main.async {
                            self.tableView.reloadData()
                        }
                    }
                }
            }
    }
}
func uniq<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
    var buffer = [T]()
    var added = Set<T>()
    for elem in source {
        if !added.contains(elem) {
            buffer.append(elem)
            added.insert(elem)
        }
    }
    return buffer
}


  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
 
    return self.budgetData.count
}

struct Transaction {
var catId : String? = nil
var title: String
var dateInfo: String
var image: UIImage
var amount: Double
var annualPercentageRate: Double?
var trailingSubText: String?
var uid: String?
var outOfString: String?
var category: String?
var dictionary:[String:Any]{
    return [
        "title": title,
        "dateInfo":dateInfo,
        "amount":amount,
        "annualPercentageRate":annualPercentageRate,
        "trailingSubText":trailingSubText,
        "uid": uid,
        "outOfString": outOfString,
        "category": category
    ]
}

} [1]: Removing duplicate elements from an array in Swift

soRazor
  • 137
  • 9
  • Can you show the code for your `Transaction` model? – jnpdx Feb 25 '21 at 23:51
  • At a high level, I would think that loading your results into a Dictionary with transId as the key and the Transaction as the value would give you a dictionary containing a unique list of Transactions. – Nicholas Rees Feb 25 '21 at 23:58

1 Answers1

0

You need to make Transaction object Hashable. Try this

struct Transaction{
     var transId: String
}
extension Transaction: Hashable{
     static func ==(lhs: Transaction, rhs: Transaction) -> Bool {
        return lhs.transId == rhs.transId
     }
 }


var budgetData = [Transaction(transId: "a"), Transaction(transId:"c"), 
                  Transaction(transId: "a"), Transaction(transId: "d")]
var tranSet = Set<Transaction>()
budgetData = budgetData.filter { (transaction) -> Bool in

   if !tranSet.contains(transaction){
      tranSet.insert(transaction)
      return true
    }
    return false
}
Shubham Daramwar
  • 287
  • 2
  • 12
  • Set `insert` method returns a property called `inserted` exactly for this purpose. Btw you can use `RangeReplaceableCollection` mutating method `removeAll(where:)`. Check this [post](https://stackoverflow.com/a/34712330/2303865) ==> `budgetData.removeAll{!set.insert($0).inserted}` – Leo Dabus Feb 26 '21 at 14:09