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

Swift枚举:忽略关联值枚举唯一用例,实现连续整数映射

问题翻译

我希望实现快速枚举,将Score枚举转换为从0开始的连续唯一整数值序列,每个枚举case对应一个值,赋值顺序与声明顺序一致。在这个示例中,序列应为0、1、2。有没有现成的表达式可以实现这个需求?还是只能手动编写?另外我需要两种Hashable实现,以便分别统计所有可能的变体数量(包含关联值的不同组合)和枚举case的总数。

提供的代码示例:

enum Score: {
    case snap(Rank) // 6 varieties
    case double(Power) // 4 varieties
    case highFive

    var value: Int {
        // ...
    }
}

enum Rank: Int {
//..
}

enum Power: Int {
// ..
}

解决方案

1. 给每个枚举Case分配连续值(0、1、2)

不需要手动逐个赋值,通过switch语句映射每个case到对应索引即可,完全匹配声明顺序:

enum Score: Hashable {
    case snap(Rank)
    case double(Power)
    case highFive

    // 每个case对应的连续值,按声明顺序分配0、1、2
    var caseValue: Int {
        switch self {
        case .snap: return 0
        case .double: return 1
        case .highFive: return 2
        }
    }
}

如果想更自动化(比如新增case时无需修改caseValue),可以手动实现CaseIterable协议(带关联值的枚举无法自动合成该协议),通过allCases的索引获取值:

extension Score: CaseIterable {
    // 按声明顺序定义所有case的代表实例(关联值不影响case判断)
    static var allCases: [Score] {
        [.snap(.one), .double(.low), .highFive]
    }
}

// 基于CaseIterable的caseValue实现
var caseValue: Int {
    Score.allCases.firstIndex(of: self)!
}

注意:需保证allCases的顺序与枚举声明顺序一致,且该方式仅适用于只关心case本身、不关联具体关联值的场景。

2. 给所有变体(Case+关联值组合)分配连续值

如果需要给每个包含关联值的具体变体分配唯一连续值(比如snap(Rank.one)对应0,snap(Rank.two)对应1…highFive对应10),可以结合关联枚举的CaseIterable和rawValue实现:

// 先让Rank和Power实现CaseIterable与Int rawValue
enum Rank: Int, CaseIterable {
    case one, two, three, four, five, six // 共6种
}

enum Power: Int, CaseIterable {
    case low, medium, high, extreme // 共4种
}

enum Score: Hashable {
    case snap(Rank)
    case double(Power)
    case highFive

    var variantValue: Int {
        switch self {
        case .snap(let rank):
            // snap的变体从0开始,对应Rank的rawValue
            return rank.rawValue
        case .double(let power):
            // double的变体接在snap之后,先加snap的总数
            return Rank.allCases.count + power.rawValue
        case .highFive:
            // highFive接在所有snap和double变体之后
            return Rank.allCases.count + Power.allCases.count
        }
    }
}

3. 两种Hashable实现

  • 默认合成的Hashable:Swift会自动为Score合成Hashable实现(只要Rank和Power也实现Hashable),该实现会同时考虑case和关联值,不同的变体(比如.snap(.one)和.snap(.two))会被视为不同的哈希对象,适合统计变体总数。
  • 仅按Case哈希的实现:如果需要只区分case、忽略关联值的哈希逻辑,可以手动实现自定义哈希结构:
extension Score {
    struct CaseOnlyHash: Hashable {
        private let caseIndex: Int

        init(_ score: Score) {
            switch score {
            case .snap: self.caseIndex = 0
            case .double: self.caseIndex = 1
            case .highFive: self.caseIndex = 2
            }
        }

        func hash(into hasher: inout Hasher) {
            hasher.combine(caseIndex)
        }

        static func == (lhs: Self, rhs: Self) -> Bool {
            lhs.caseIndex == rhs.caseIndex
        }
    }
}

使用时只需将Score实例包装为CaseOnlyHash,即可按case进行哈希比较,适合统计枚举case总数。

4. 统计总数

  • 枚举case总数:可以直接硬编码3,或通过手动实现的CaseIterable的Score.allCases.count获取。
  • 变体总数:通过Rank.allCases.count + Power.allCases.count + 1计算(+1对应无关联值的highFive)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:40:39