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 […]
…
}
}
}