基于带关联值的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
相关产品推荐
相关产品推荐

