Swift - 在具有关联值的枚举数组中查找对象

Swift - find object in array of enums with associated values

我有这个枚举:

enum Animal {       
    case cat(CatModel)
    case dog(DogModel)
}

还有一组动物:

var animals: [Animal]

我需要通过 属性 在这个数组中找到 Dog 没有的 Cat 对象。 litterBoxId 例如。

let cat = animals.first(where: {[=13=].litterBoxId == 7})

这当然有错误:

Value of type 'MyViewController.Animal' has no member 'litterBoxId'

我怎样才能做到这一点?我也试过了

([=15=] as CatModel).litterBoxId

这可能不是很好地使用枚举,但它可以工作的方式如下:

struct CatModel {
    let litterBoxID: Int
}

struct DogModel {
    let litterBoxID: Int
}

enum Animal {       
    case cat(CatModel)
    case dog(DogModel)
    
    var litterBoxId: Int {
        switch self {
        case .cat(let cat): return cat.litterBoxID
        case .dog(let dog): return dog.litterBoxID
        }
    }
}

var animals: [Animal] = []
let cat = animals.first(where: { [=10=].litterBoxId == 7 })

你最好使用协议:

struct CatModel: Animal {
    let litterBoxID: Int
}

struct DogModel: Animal {
    let litterBoxID: Int
}

protocol Animal {
    var litterBoxID: Int { get }
}

var animals: [Animal] = []
let cat = animals.first(where: { [=11=].litterBoxID == 7 })

您可以通过两种方式使用模式匹配来完成此操作。

使用开关:

let cat = animals.first(where: {
    switch [=10=] {
    case .cat(let catModel) where catModel.litterBoxId == 7:
        return true
    default:
        return false
    }
})

或者如果:

let cat = animals.first(where: {
    if case .cat(let catModel) = [=11=], catModel.litterBoxId == 7 {
        return true
    }
    return false
})

更新:正如@Alexander-ReinstateMonica在他的commnet中提到的那样,将此逻辑隐藏在这样的函数后面会更合适:

extension Animal {
    func matches(litterboxID: Int) -> Bool {
        switch self {
        case .cat(let catModel) where catModel.litterBoxId == 7:
            return true
        default:
            return false
        }
    }
}

然后你的代码会更干净:

let cat = animals.first(where: { [=13=].matches(litterboxID: 7) })