假设我有这个枚举:
enum Item {
case foo(String)
case bar(String)
}
及其列表:
let items: [Item] = [.foo("aa"), .bar("bb")]
我想找到它的第一 foo
项,这就是我所做的:
items.first { (item) -> Bool in
switch item {
case .foo:
return true
default:
return false
}
}
有什么优雅的方法可以写类似的东西:
items.first { case .foo = $0 }
(上面的代码显然无效)
答案 0 :(得分:3)
如果您有一个枚举数具有关联值的枚举,则可以使用switch
语句替换if case (let) ... else
语句,因为您只在搜索给定的枚举数模式(其余均不搜索- > else
)。例如:
let item = items.first {
if case .foo = $0 { return true }
else { return false }
}
=
是赋值,而==
是相等比较。在这里,您需要后者:
let item = items.first { $0 == .foo }
// or
let item = items.first { .foo == $0 }
您还可以使用~=
运算符来使用模式匹配:
let item = items.first { $0 ~= .foo }
// or
let item = items.first { .foo ~= $0 }
答案 1 :(得分:1)
first
不会做任何有用的事情。我认为您想要contains
。
items.contains { Item.foo ~= $0 }
无论如何,您将需要以下内容:
/// Match `enum` cases with associated values, while disregarding the values themselves.
/// - Parameter case: Looks like `Enum.case`.
public func ~= <Enum: Equatable, AssociatedValue>(
case: (AssociatedValue) -> Enum,
instance: Enum
) -> Bool {
Mirror.associatedValue(of: instance, ifCase: `case`) != nil
}
/// Match `enum` cases with associated values, while disregarding the values themselves.
/// - Parameter case: Looks like `Enum.case`.
public func ~= <Enum, AssociatedValue>(
case: (AssociatedValue) -> Enum,
instance: Enum
) -> Bool {
Mirror.associatedValue(of: instance, ifCase: `case`) != nil
}
public extension Mirror {
/// Get an `enum` case's `associatedValue`.
static func associatedValue<AssociatedValue>(
of subject: Any,
_: AssociatedValue.Type = AssociatedValue.self
) -> AssociatedValue? {
guard let childValue = Self(reflecting: subject).children.first?.value
else { return nil }
if let associatedValue = childValue as? AssociatedValue {
return associatedValue
}
let labeledAssociatedValue = Self(reflecting: childValue).children.first
return labeledAssociatedValue?.value as? AssociatedValue
}
/// Get an `enum` case's `associatedValue`.
/// - Parameter case: Looks like `Enum.case`.
static func associatedValue<Enum: Equatable, AssociatedValue>(
of instance: Enum,
ifCase case: (AssociatedValue) throws -> Enum
) rethrows -> AssociatedValue? {
try associatedValue(of: instance)
.filter { try `case`($0) == instance }
}
/// Get an `enum` case's `associatedValue`.
/// - Parameter case: Looks like `Enum.case`.
static func associatedValue<Enum, AssociatedValue>(
of instance: Enum,
ifCase case: (AssociatedValue) throws -> Enum
) rethrows -> AssociatedValue? {
try associatedValue(of: instance).filter {
.equate(try `case`($0), to: instance) {
Self(reflecting: $0).children.first?.label
}
}
}
}
public extension Optional {
/// Transform `.some` into `.none`, if a condition fails.
/// - Parameters:
/// - isSome: The condition that will result in `nil`, when evaluated to `false`.
func filter(_ isSome: (Wrapped) throws -> Bool) rethrows -> Self {
try flatMap { try isSome($0) ? $0 : nil }
}
}
public extension Equatable {
/// Equate two values using a closure.
static func equate<Wrapped, Equatable: Swift.Equatable>(
_ optional0: Wrapped?, to optional1: Wrapped?,
using transform: (Wrapped) throws -> Equatable
) rethrows -> Bool {
try optional0.map(transform) == optional1.map(transform)
}
}