Home > Blockchain >  getting error: Binary operator '==' cannot be applied to two 'x' operands, how t
getting error: Binary operator '==' cannot be applied to two 'x' operands, how t

Time:11-10

I am trying to remove 3 of my yellow objects in my array 'deck'. The array is made of Cards objects. I used:

var counter = 3
var newArr = arr.filter {
    if counter > 0, $0 == yellow {
        counter -= 1
        return false
    }
    return true
}

and I get the error: Binary operator '==' cannot be applied to two Cards operands

I have a struct:

import UIKit

struct Cards {
    var type: String
    var income: Int
    var images: [UIImage]
    
    init(type: String, income: Int, images: [UIImage]) {
        self.type = type
        self.income = income
        self.images = images
    }
}

let yellow = Cards(type: "yellow", income: 0, images: [#imageLiteral(resourceName: "yellow1"), #imageLiteral(resourceName: "yellow2")])
let darkBlue = Cards(type: "dark blue", income: 2, images: [#imageLiteral(resourceName: "dark1"), #imageLiteral(resourceName: "dark2")])
let red = Cards(type: "red", income: 2, images: [#imageLiteral(resourceName: "red1"), #imageLiteral(resourceName: "red2")])
let green = Cards(type: "green", income: 1, images: [#imageLiteral(resourceName: "green1"), #imageLiteral(resourceName: "green2")])
let blue = Cards(type: "blue", income: 3, images: [#imageLiteral(resourceName: "blue1"), #imageLiteral(resourceName: "blue2")])

I have an array deck = [Cards], which I created and then filled with a generator I created which makes the first 5 of seven cards yellow. When I print the deck in the console, it reads as:

[game.Cards(type: "yellow", income: 0, images: [<UIImage:0x6000037a8cf0 named(main: yellow1) {416.66666666666669, 583.33333333333337}>, <UIImage:0x6000037a8e10 named(main: yellow2) {416.66666666666669, 583.33333333333337}>]), outthegame.Cards(type: "yellow", income: 0, images: [<UIImage:0x6000037a8cf0 named(main: yellow1) {416.66666666666669, 583.33333333333337}>, <UIImage:0x6000037a8e10 named(main: yellow2) {416.66666666666669, 583.33333333333337}>]), outthegame.Cards(type: "yellow", income: 0, images: [<UIImage:0x6000037a8cf0 named(main: yellow1) {416.66666666666669, 583.33333333333337}>, <UIImage:0x6000037a8e10 named(main: yellow2) {416.66666666666669, 583.33333333333337}>]), outthegame.Cards(type: "yellow", income: 0, images: [<UIImage:0x6000037a8cf0 named(main: yellow1) {416.66666666666669, 583.33333333333337}>, <UIImage:0x6000037a8e10 named(main: yellow2) {416.66666666666669, 583.33333333333337}>]), outthegame.Cards(type: "yellow", income: 0, images: [<UIImage:0x6000037a8cf0 named(main: yellow1) {416.66666666666669, 583.33333333333337}>, <UIImage:0x6000037a8e10 named(main: yellow2) {416.66666666666669, 583.33333333333337}>]), outthegame.Cards(type: "blue", income: 3, images: [<UIImage:0x6000037a9170 named(main: blue1) {416.66666666666669, 583.33333333333337}>, <UIImage:0x6000037a8f30 named(main: blue2) {416.66666666666669, 583.33333333333337}>]), outthegame.Cards(type: "green", income: 1, images: [<UIImage:0x6000037a0ab0 named(main: green1) {416.66666666666669, 583.33333333333337}>, <UIImage:0x6000037a0bd0 named(main: green2) {416.66666666666669, 583.33333333333337}>])]

How to check if the deck has 3 yellow cards and then remove them from the deck?

CodePudding user response:

== is defined on Equatable, which your Cards type is not. You either need to make Cards conform to equatable, and decide which of your properties counts towards "equal" (The same type? the same income? both? What about the images?), or compare directly on the properties you do care about.

CodePudding user response:

As @jrturton has pointed out your Cards type doesn't conform to Equatable protocol, hence you can't use the == operator for comparisons between two of its instances.

Moreover the code you've posted doesn't really match your underlaying question: "How to check if the deck has 3 yellow cards and then remove them from the deck?"

In your code you just remove yellow cards even if it contains just 1 yellow card.

So to fulfil your real question you should first check if the deck contains at least 3 yellow cards, and then remove the first 3 yellow cards:

var yellowsCount = 0
for card in deck where card.type == "yellow" {
    yellowsCount  = 1
    guard yellowsCount < 3 else { break }
}
if yellowsCount == 3 {
    for _ in 1...3 {
      deck.removeFirst { $0.type == "yellow" }
    }

}

But of course this solution would work only for the first 3 yellow cards in the deck. What do you really need to achieve? Perhaps remove all triplets of yellow cards? Then you might as well adopt another approach:

var yellowsCount = 0
let newDeck: Array<Cards> = deck.reduce([], {
    if $1.type == "yellow" {
       yellowsCount  = 1
       guard 
           yellowsCount < 3 
       else {
           yellowsCount = 0
           return $0.filter { c in c.type != "yellow" }
       }
    } 
    return $0   [$1]
}

All of the above is based on the fact that you'd intended to check the type property on Cards for yellow value. Anyway for that too I'd recommend a different approach than using a String based approach for that property, and instead use a nested enum Color for that value:

struct Cards {
   enum Color: CaseIterable {
       case yellow, blue, darkBlue, red, green
    }
    var type: Color
    var income: Int
    var images: Array<UIImage>

}

In this way you'll do comparisons for the type property by adopting switch or if case let constructs: both are less error-prone than string based comparison (typos and so on).

Moreover with the above approach if you decide that a Card of certain type always has the same images, you can turn images property into a computed property on the nested enum as in:

extension Color {
    var images: Array<UIImage> {
        switch self {
        case .yellow: return [yellowP1, yellowP2]
        case .green: return [greenP1, greenP2, greenP3]
        case .blue: return []
        
        }
    }

}
  • Related