You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于带关联值的Swift枚举过滤数组(不提及关联值)

解决带关联值枚举的数组子集匹配问题

我懂你的困扰——带关联值的枚举没法直接用普通相等判断来筛选数组:如果只关心枚举的成员类型(比如只要是.c不管关联值是什么),或者需要精确匹配关联值,得用不同的方式处理。下面给你两种实用的实现方案,还有更灵活的拓展写法:

方案1:匹配枚举成员类型(忽略关联值)

如果你的需求是「只要是某个枚举成员,不管关联值是什么都筛选出来」,可以给Foo加个辅助属性标识成员类型,或者直接用模式匹配判断:

实现代码

enum Foo {
    case a
    case b
    case c(String?)
    
    // 新增枚举用来标记成员类型(不含关联值)
    enum CaseType {
        case a, b, c
    }
    
    var caseType: CaseType {
        switch self {
        case .a: return .a
        case .b: return .b
        case .c: return .c
        }
    }
}

struct Bar {
    var foo: Foo
}

let array: [Bar] = [
    Bar(foo: .a),
    Bar(foo: .c(nil)),
    Bar(foo: .c("someString"))
]

// 筛选并打印匹配指定成员类型的元素
func printOnly(matchingCaseType type: Foo.CaseType) {
    let filtered = array.filter { $0.foo.caseType == type }
    filtered.forEach { print($0.foo) }
}

// 调用示例:打印所有.c的元素
printOnly(matchingCaseType: .c)
// 输出:
// c(nil)
// c(Optional("someString"))

嫌加辅助枚举麻烦?也可以直接用模式匹配的闭包实现:

func printOnly(matchingMember member: Foo) {
    let filtered = array.filter { bar in
        switch (bar.foo, member) {
        case (.a, .a), (.b, .b), (.c, .c): return true
        default: return false
        }
    }
    filtered.forEach { print($0.foo) }
}

// 调用示例
printOnly(matchingMember: .c)

方案2:精确匹配(包括关联值)

如果需要「完全匹配枚举成员和关联值」,只需要让Foo遵守Equatable协议——Swift会自动为带关联值的枚举合成相等判断逻辑:

实现代码

// 让Foo遵守Equatable
enum Foo: Equatable {
    case a
    case b
    case c(String?)
}

struct Bar {
    var foo: Foo
}

let array: [Bar] = [
    Bar(foo: .a),
    Bar(foo: .c(nil)),
    Bar(foo: .c("someString"))
]

// 筛选并打印精确匹配的元素
func printOnly(matchingExact caseValue: Foo) {
    let filtered = array.filter { $0.foo == caseValue }
    filtered.forEach { print($0.foo) }
}

// 调用示例1:只匹配.c(nil)
printOnly(matchingExact: .c(nil))
// 输出:c(nil)

// 调用示例2:只匹配.c("someString")
printOnly(matchingExact: .c("someString"))
// 输出:c(Optional("someString"))

拓展:更灵活的自定义匹配

如果需要更复杂的筛选逻辑(比如匹配关联值非空的.c),可以直接传入判断闭包,自由度拉满:

func printOnly(where condition: (Foo) -> Bool) {
    array.filter { condition($0.foo) }.forEach { print($0.foo) }
}

// 调用示例:匹配所有.c且关联值非空的元素
printOnly {
    if case .c(let str?) = $0 {
        return true
    }
    return false
}
// 输出:c(Optional("someString"))

内容的提问来源于stack exchange,提问作者Noam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:33:45