user8653398
user8653398

Reputation:

Issue with checking if the array contains an object

This might seem as a basic question..but I'm confused regarding how to achieve this with the new swift syntax. On the click of a button on the collection view I'm having something like this....

    let productObject = productData1[(indexPath?.row)!]
    self.myArray.append(productObject)

Now when I click on that button again I want to check if myArray has the productObject already so that it will not be added to the array again...Hope somebody can help...

EDIT: productData1 is a type of struct Product like so...

struct Product {
    let name : String
    let id : String
    var images = [ProductImage]()
    var theRate : String
    var quantity: String
    var sku: String
    var prdCateg: String
    var prodDescr: String
    var mrp: String
    var prodcutImage: ProductImage?

    init(name : String, id: String, theRate: String, quantity: String, sku: String, prdCateg:String, prodDescr: String, prodcutImage: ProductImage?, mrp: String) {
        self.name = name
        self.id = id
        self.theRate = theRate
        self.quantity = quantity
        self.sku = sku
        self.prdCateg = prdCateg
        self.prodDescr = prodDescr
        self.prodcutImage = prodcutImage
        self.mrp = mrp

    }

    mutating func add(image: ProductImage) {
        images.append(image)
    }
}

Upvotes: 1

Views: 101

Answers (4)

user2225177
user2225177

Reputation: 46

If you don't care about the order of your objects inside myArray, one solution would be do use a Set. First of all you'll need to make your struct Product compliant to Hashable. By taking a look at your struct we can assume that two products are equals if their IDs are equals.

extension Product: Hashable {

    var hashValue: Int { return id.hashValue}

    static func ==(lhs: Product, rhs: Product) -> Bool {
        return lhs.id == rhs.id
    }
}

You redefine myArray as followed:

var myArray: Set<Product> = [] // Creating the Set of `Products`

// inserting product with id "123"
myArray.insert(Product(name: "name",
                       id: "123",
                       images: [],
                       theRate: "",
                       quantity: "",
                       sku: "",
                       prdCateg: "",
                       prodDescr: "",
                       mrp: "", prodcutImage: nil))

// Trying to insert product with id "123" but it already exists,
// It won't be added to myArray
myArray.insert(Product(name: "name",
                       id: "123",
                       images: [],
                       theRate: "",
                       quantity: "",
                       sku: "",
                       prdCateg: "",
                       prodDescr: "",
                       mrp: "", prodcutImage: nil))

print(myArray.count) // 1

Upvotes: 1

tiko
tiko

Reputation: 61

ProductImage should conform protocol Equatable. Then you can check is objects of ProductImage are the same, and accordingly is images.contains(image) before add new one.

To conform protocol you need to implement func == for ProductImage.

Something like

func ==(lhs: ProductImage, rhs: ProductImage) -> Bool {
    return lhs.imageUrl == rhs.imageUrl
}

Upvotes: 0

DanielH
DanielH

Reputation: 685

Here are 2 solutions. The first one is more efficient IMO.

SOLUTION I - maintain additional Mapping Data Source

var myArray: [Product] = []
var myDictionary: [String : Product] = [:]

func add(newProduct product: Product) {

    // Add only if product isn't contained in datasource (Test in O(1))
    guard myDictionary[product.id] == nil else {
        return
    }

    myArray.append(product)
    myDictionary[product.id] = product
}

Memory motivation / consideration: The memory cost of additional data-source is relatively low because of the lazy manner that Swift language copies structs. Both array and dictionary hold the same instances of Products until their inner content is changed.

SOLUTION II (Less efficient) - use contains method of the collection view (Iterate the array every time

var myArray: [Product] = []

func add(newProduct product: Product) {

    // Test while `contains`
    guard !myArray.contains { $0.id == product.id } else {
        return
    }

    myArray.append(product)
}

Upvotes: 0

Bapu
Bapu

Reputation: 94

Hope this will help you..

  let productObject = productData1[(indexPath?.row)!]

     let filteredArray = self.myArray.filter(){
             return $0.id == productObject.id
          }
   if filteredArray.count == 0 {
      self.myArray.append(productObject)
             }

Upvotes: 0

Related Questions