1

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)
    }
}
11
  • Is what type of productData1? Commented Nov 1, 2017 at 13:18
  • It's a type of struct Product. Like this...var productData1 = [Product]() Commented Nov 1, 2017 at 13:19
  • This is well covered in Array documentation. Did you read it? Commented Nov 1, 2017 at 13:19
  • Product is a class? Commented Nov 1, 2017 at 13:20
  • Its a struct @SalmanGhumsani...I have updated the question... Commented Nov 1, 2017 at 13:22

4 Answers 4

1

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
Sign up to request clarification or add additional context in comments.

Comments

0

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)
}

3 Comments

I'll have to call this method where I want to add/don't add the element to array right..?
@bws - Yes, call add(newProduct:) method wherever you need in order to add a new object to your array. As i've said, the first option is better imo.
Glad i could help :-)
0

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)
             }

2 Comments

Forced unwrapping is bad – id is not an optional – Using filter instead of contains is ineffective.
your solution also worked, @Bapu..but accepted the other answer since it was given in more detail...have given an upvote though...:)
0

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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.