简体   繁体   English

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

[英]Swift - find object in array of enums with associated values

I have this enum:我有这个枚举:

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

And an array of animals:还有一系列动物:

var animals: [Animal]

I need to find a Cat object in this array by a property that Dog doesn't have.我需要通过 Dog 没有的属性在此数组中找到 Cat object。 litterBoxId for example.例如litterBoxId

let cat = animals.first(where: {$0.litterBoxId == 7})

This of course has an error:这当然有一个错误:

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

How can I accomplish this?我怎样才能做到这一点? I also tried我也试过

($0 as CatModel).litterBoxId

This probably isn't a good use of enums, but here is how it could work:这可能不是对枚举的良好使用,但它是如何工作的:

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: { $0.litterBoxId == 7 })

You would be much better off using a protocol:使用协议会更好:

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: { $0.litterBoxID == 7 })

You can use pattern matching to accomplish this with 2 ways.您可以通过 2 种方式使用模式匹配来完成此操作。

Using switch:使用开关:

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

or if:或者如果:

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

Update : As @Alexander-ReinstateMonica mentioned in his commnet, it would be more appropriate to hide this logic behind a function like this:更新:正如@Alexander-ReinstateMonica 在他的 commnet 中提到的,将这个逻辑隐藏在 function 后面会更合适,如下所示:

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

and then your code will be much cleaner:然后你的代码会更干净:

let cat = animals.first(where: { $0.matches(litterboxID: 7) })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM