Что вам нужно, так это Swift KeyPath .
В моей реализации Sets (Zotz!) Это то, что я делаю. Во-первых, я использую перечисления с необработанными значениями Int для четырех атрибутов карты. Это позволяет мне представлять любой атрибут как общий тип (Int). Я выражаю эти необработанные значения в виде вычисляемых свойств и продаю список всех четырех вычисляемых свойств в виде массива ключевых путей (обратите внимание, это Swift 5):
public struct Card: Codable, CustomStringConvertible {
let itsColor : Color
let itsNumber : Number
let itsShape : Shape
let itsFill : Fill
var itsColorRaw : Int { return itsColor.rawValue }
var itsNumberRaw : Int { return itsNumber.rawValue }
var itsShapeRaw : Int { return itsShape.rawValue }
var itsFillRaw : Int { return itsFill.rawValue }
public static let attributes : [KeyPath<Card, Int>] = [
\itsColorRaw, \itsNumberRaw, \itsShapeRaw, \itsFillRaw
]
// ...
}
Хорошо, теперь легко определить, является ли данная тройка карт действительным совпадением:
private func isCorrectCards(_ cards:[Card]) -> Bool {
func evaluateOneAttribute(_ nn:[Int]) -> Bool {
let allSame = (nn[0] == nn[1]) && (nn[1] == nn[2])
let allDiff = (nn[0] != nn[1]) && (nn[1] != nn[2]) && (nn[2] != nn[0])
return allSame || allDiff
}
return Card.attributes.allSatisfy { att in
evaluateOneAttribute(cards.map{$0[keyPath:att]})
}
}