我如何以通用方式知道具有关联值的枚举类型?
How do I know the type of an enum with associated value in a generic way?
前几天问过this question.
绝妙的解决方案是这样的:
enum MyEnum {
case one
case two
case three(user: String)
func isOfSameType(_ other: MyEnum) -> Bool {
switch (self, other) {
case (.one, .one):
return true
case (.two, .two):
return true
case (.three, .three):
return true
default:
return false
}
}
}
var array: [MyEnum] = []
func add(_ value: MyEnum) {
if array.contains(where: { value.isOfSameType([=10=]) }) { return }
array.append(value)
}
现在,冷血分析,这似乎完全是黑魔法。
交换机如何比较没有参数的东西?
但现在我需要检查 stack
上的最后一个元素是否属于 three
。
类似
if array!.last.isOfType(.three) {
}
这行不通。 Xcode 需要 .three 的参数。
因为我目前还不了解我所掌握的内容,所以我不知道该怎么做。
请试试这个:
执行三个协议Equatable, Hashable and CustomStringConvertible
public enum MyEnum: Equatable, Hashable, CustomStringConvertible {
case one
case two
case three(user: String)
// CustomStringConvertible
// create unique string for each case
public var description: String {
switch self {
case .one:
return "one"
case .two:
return "two"
case .three:
return "three"
}
}
// Hashable
public func hash(into hasher: inout Hasher) {
hasher.combine(self.description)
}
// Equatable
public static func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
var array: [MyEnum] = []
func add(_ value: MyEnum) {
// option one
// if array.last!.hashValue == value.hashValue {
// return
// }
// option two
if array.contains(value) {
return
}
array.append(value)
}
add(.one)
add(.one)
add(.two)
add(.two)
add(.three(user: "hello"))
add(.three(user: "hi"))
for item in array {
print(item.description)
}
结果打印:
one
two
three
据我了解,您想知道为什么您的 switch 语句带有
case (.three, .three):
return true
找到了,但是
if array!.last.isOfType(.three) { /* ... */ }
导致编译器错误。
问题是switch语法有点特殊(模式匹配),不能在函数调用中使用。
由于您似乎想忽略 user
的值,您可以执行以下操作:
if case .three = array!.last { /* ... */ }
这正是 switch 语句所做的 - 它忽略分配的值。
如果你想调用一个函数,你需要传入枚举的 concrete
实例,并且由于用户被 isOfType
忽略,使用 dummy 以下语句中的值将起作用:
if array!.last.isOfSameType(.three(user:"dummy")) { /* ... */ }
Swift Enum 很特别,有很多其他人没有的特性。然而,它是一个枚举,就像 C 风格的枚举一样简单,就像整数一样。枚举的实例只是一个值。
在你的例子中,
enum MyEnum {
case one
case two
case three(user: String)
}
假设你有一个数组,
let arrayMyEnum: [MyEnum] = [.one, .two, .three(user: "Mike"), .two, .three(user: "John")]
那么,你可以,
// basic approach
arrayMyEnum.contains {
switch [=12=] {
case .three(let user):
return true
default:
return false
}
}
// Using optional pattern
arrayMyEnum.contains {
if case .three(let user) = [=12=] {
return true
} else {
return false
}
}
或者如您在评论中所述,您不关心包装值,而只是想检查实例是否属于特定情况。然后你可以忽略包装值,
arrayMyEnum.contains {
switch [=13=] {
case .three:
return true
default:
return false
}
}
arrayMyEnum.contains {
if case .three = [=13=] {
return true
} else {
return false
}
}
我猜上面就是你问的。
通知,
在底层,具有包装值的枚举实例具有用于比较的散列。因此,如果您想使用 ==
相等运算符执行相等性,编译器会警告您您的枚举需要符合 Hashable.
例如,如果你想比较,
enum MyEnum: Hashable {
case one
case two
case three(user: String)
}
MyEnum.three(user: "SomeValue") == MyEnum.three(user: "AnotherValue")
本身是 Hashable 的 Swfit 类型的枚举是隐式可哈希的。
在您的例子中,枚举具有包装值,包装值需要是 Hashable。由于 String 已经是 Hashable,您只需要声明 Hashable 一致性。
只有当包装类型不是 Hashable 时,您才需要自己编写 ==
和 hasher
方法,这在大多数情况下非常简单。
读数
Language Reference #Enumeration Case Pattern, Optional Pattern.
您只需要使您的枚举符合 Equatable 并比较关联的值是否相等:
enum MyEnum: Equatable {
case one
case two
case three(user: String)
}
var array: [MyEnum] = []
func add(_ value: MyEnum) {
if array.contains(value) { return }
array.append(value)
}
add(.one)
add(.one)
array
add(.three(user: "a"))
add(.three(user: "b"))
add(.three(user: "a"))
array[0] // one
array[1] // three(user: "a")
array[2] // three(user: "b")
检查最后一个元素是否大小写.three:
if case .three = array.last {
print(true)
}
前几天问过this question.
绝妙的解决方案是这样的:
enum MyEnum {
case one
case two
case three(user: String)
func isOfSameType(_ other: MyEnum) -> Bool {
switch (self, other) {
case (.one, .one):
return true
case (.two, .two):
return true
case (.three, .three):
return true
default:
return false
}
}
}
var array: [MyEnum] = []
func add(_ value: MyEnum) {
if array.contains(where: { value.isOfSameType([=10=]) }) { return }
array.append(value)
}
现在,冷血分析,这似乎完全是黑魔法。
交换机如何比较没有参数的东西?
但现在我需要检查 stack
上的最后一个元素是否属于 three
。
类似
if array!.last.isOfType(.three) {
}
这行不通。 Xcode 需要 .three 的参数。
因为我目前还不了解我所掌握的内容,所以我不知道该怎么做。
请试试这个:
执行三个协议Equatable, Hashable and CustomStringConvertible
public enum MyEnum: Equatable, Hashable, CustomStringConvertible {
case one
case two
case three(user: String)
// CustomStringConvertible
// create unique string for each case
public var description: String {
switch self {
case .one:
return "one"
case .two:
return "two"
case .three:
return "three"
}
}
// Hashable
public func hash(into hasher: inout Hasher) {
hasher.combine(self.description)
}
// Equatable
public static func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
var array: [MyEnum] = []
func add(_ value: MyEnum) {
// option one
// if array.last!.hashValue == value.hashValue {
// return
// }
// option two
if array.contains(value) {
return
}
array.append(value)
}
add(.one)
add(.one)
add(.two)
add(.two)
add(.three(user: "hello"))
add(.three(user: "hi"))
for item in array {
print(item.description)
}
结果打印:
one
two
three
据我了解,您想知道为什么您的 switch 语句带有
case (.three, .three):
return true
找到了,但是
if array!.last.isOfType(.three) { /* ... */ }
导致编译器错误。
问题是switch语法有点特殊(模式匹配),不能在函数调用中使用。
由于您似乎想忽略 user
的值,您可以执行以下操作:
if case .three = array!.last { /* ... */ }
这正是 switch 语句所做的 - 它忽略分配的值。
如果你想调用一个函数,你需要传入枚举的 concrete
实例,并且由于用户被 isOfType
忽略,使用 dummy 以下语句中的值将起作用:
if array!.last.isOfSameType(.three(user:"dummy")) { /* ... */ }
Swift Enum 很特别,有很多其他人没有的特性。然而,它是一个枚举,就像 C 风格的枚举一样简单,就像整数一样。枚举的实例只是一个值。
在你的例子中,
enum MyEnum {
case one
case two
case three(user: String)
}
假设你有一个数组,
let arrayMyEnum: [MyEnum] = [.one, .two, .three(user: "Mike"), .two, .three(user: "John")]
那么,你可以,
// basic approach
arrayMyEnum.contains {
switch [=12=] {
case .three(let user):
return true
default:
return false
}
}
// Using optional pattern
arrayMyEnum.contains {
if case .three(let user) = [=12=] {
return true
} else {
return false
}
}
或者如您在评论中所述,您不关心包装值,而只是想检查实例是否属于特定情况。然后你可以忽略包装值,
arrayMyEnum.contains {
switch [=13=] {
case .three:
return true
default:
return false
}
}
arrayMyEnum.contains {
if case .three = [=13=] {
return true
} else {
return false
}
}
我猜上面就是你问的。
通知,
在底层,具有包装值的枚举实例具有用于比较的散列。因此,如果您想使用 ==
相等运算符执行相等性,编译器会警告您您的枚举需要符合 Hashable.
例如,如果你想比较,
enum MyEnum: Hashable {
case one
case two
case three(user: String)
}
MyEnum.three(user: "SomeValue") == MyEnum.three(user: "AnotherValue")
本身是 Hashable 的 Swfit 类型的枚举是隐式可哈希的。
在您的例子中,枚举具有包装值,包装值需要是 Hashable。由于 String 已经是 Hashable,您只需要声明 Hashable 一致性。
只有当包装类型不是 Hashable 时,您才需要自己编写 ==
和 hasher
方法,这在大多数情况下非常简单。
读数
Language Reference #Enumeration Case Pattern, Optional Pattern.
您只需要使您的枚举符合 Equatable 并比较关联的值是否相等:
enum MyEnum: Equatable {
case one
case two
case three(user: String)
}
var array: [MyEnum] = []
func add(_ value: MyEnum) {
if array.contains(value) { return }
array.append(value)
}
add(.one)
add(.one)
array
add(.three(user: "a"))
add(.three(user: "b"))
add(.three(user: "a"))
array[0] // one
array[1] // three(user: "a")
array[2] // three(user: "b")
检查最后一个元素是否大小写.three:
if case .three = array.last {
print(true)
}