enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
例如,我怎么做这样的事情:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
结果示例:
♠
♥
♦
♣
enum Suit: String {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
例如,我怎么做这样的事情:
for suit in Suit {
// do something with suit
print(suit.rawValue)
}
结果示例:
♠
♥
♦
♣
当前回答
以下是我的建议。这不是完全令人满意的(我对Swift和OOP很陌生!),但也许有人可以改进它。这个想法是让每个枚举提供自己的范围信息作为.first和.last属性。它只向每个枚举添加了两行代码:仍然有点硬编码,但至少它没有复制整个集合。它确实需要将Suit enum修改为Int类型,就像Rank enum一样,而不是无类型的。
而不是重复整个解决方案,下面是我添加到。在case语句之后的某个地方(Suit enum类似):
var first: Int { return Ace.toRaw() }
var last: Int { return King.toRaw() }
以及我用来将deck构建为String数组的循环。(问题定义没有说明牌组是如何构造的。)
func createDeck() -> [String] {
var deck: [String] = []
var card: String
for r in Rank.Ace.first...Rank.Ace.last {
for s in Suit.Hearts.first...Suit.Hearts.last {
card = Rank.simpleDescription( Rank.fromRaw(r)!)() + " of " + Suit.simpleDescription( Suit.fromRaw(s)!)()
deck.append( card)
}
}
return deck
}
这并不令人满意,因为属性与元素而不是enum相关联。但它确实为“for”循环增加了清晰度。我希望它是Rank。而不是Rank.Ace.first。它适用于任何元素,但很难看。有人能演示一下如何将其提升到enum级别吗?
为了使它工作,我从Card结构中提取了createDeck方法。我不知道如何从该结构返回一个[String]数组,这似乎是一个糟糕的地方,把这样的方法无论如何。
其他回答
我使用计算属性,它返回所有值的数组(感谢这篇文章http://natecook.com/blog/2014/10/loopy-random-enum-ideas/)。但是,它也使用int原始值,但我不需要在单独的属性中重复枚举的所有成员。
Xcode 6.1在如何使用rawValue获取enum成员方面做了一点改变,所以我修正了listing。还修复了第一个rawValue错误的小错误。
enum ValidSuits: Int {
case Clubs = 0, Spades, Hearts, Diamonds
func description() -> String {
switch self {
case .Clubs:
return "♣︎"
case .Spades:
return "♠︎"
case .Diamonds:
return "♦︎"
case .Hearts:
return "♥︎"
}
}
static var allSuits: [ValidSuits] {
return Array(
SequenceOf {
() -> GeneratorOf<ValidSuits> in
var i=0
return GeneratorOf<ValidSuits> {
return ValidSuits(rawValue: i++)
}
}
)
}
}
与@Kametrixom的答案在这里,我相信返回一个数组将比返回AnySequence更好,因为你可以访问所有数组的好东西,如计数等。
以下是改写后的内容:
public protocol EnumCollection : Hashable {}
extension EnumCollection {
public static func allValues() -> [Self] {
typealias S = Self
let retVal = AnySequence { () -> AnyGenerator<S> in
var raw = 0
return AnyGenerator {
let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
return [S](retVal)
}
}
编辑: 快速进化提案SE-0194枚举案例派生集合为这个问题提出了一个水平的解决方案。我们在Swift 4.2和更新版本中看到了它。该提案还指出了一些变通方法,这些方法与这里已经提到的一些方法类似,但可能会很有趣。
为了完整起见,我也会保留我原来的职位。
这是基于@Peymmankh的回答的另一种方法,适用于Swift 3。
public protocol EnumCollection: Hashable {}
extension EnumCollection {
public static func allValues() -> [Self] {
typealias S = Self
let retVal = AnySequence { () -> AnyIterator<S> in
var raw = 0
return AnyIterator {
let current = withUnsafePointer(to: &raw) {
$0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee }
}
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
return [S](retVal)
}
我在比特和字节中跌跌撞撞,创建了一个扩展,后来我发现它与@rintaro的答案非常相似。它是这样使用的:
enum E : EnumCollection {
case A, B, C
}
Array(E.cases()) // [A, B, C]
值得注意的是,它可以在任何没有关联值的enum上使用。注意,这对于没有大小写的枚举不起作用。
与@rintaro的答案一样,这段代码使用枚举的底层表示。这种表示没有文档化,将来可能会改变,这会破坏它。我不建议在生产中使用这种方法。
代码(Swift 2.2, Xcode 7.3.1,不工作在Xcode 10):
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func cases() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyGenerator<S> in
var raw = 0
return AnyGenerator {
let current : Self = withUnsafePointer(&raw) { UnsafePointer($0).memory }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
代码(Swift 3, Xcode 8.1,不工作在Xcode 10):
protocol EnumCollection : Hashable {}
extension EnumCollection {
static func cases() -> AnySequence<Self> {
typealias S = Self
return AnySequence { () -> AnyIterator<S> in
var raw = 0
return AnyIterator {
let current : Self = withUnsafePointer(to: &raw) { $0.withMemoryRebound(to: S.self, capacity: 1) { $0.pointee } }
guard current.hashValue == raw else { return nil }
raw += 1
return current
}
}
}
}
我不知道为什么我需要typealias,但编译器抱怨没有它。
更新代码:Swift 4.2/Swift 5
enum Suit: String, CaseIterable {
case spades = "♠"
case hearts = "♥"
case diamonds = "♦"
case clubs = "♣"
}
按问题访问输出:
for suitKey in Suit.allCases {
print(suitKey.rawValue)
}
输出:
♠
♥
♦
♣
CaseIterable:提供其所有值的集合。 符合CaseIterable协议的类型通常是没有关联值的枚举。当使用CaseIterable类型时,您可以通过使用该类型的allCases属性访问该类型的所有案例的集合。
对于访问case,我们使用。allcases。更多信息请点击https://developer.apple.com/documentation/swift/caseiterable