Swift 将选项SetType映射到数组

Swift 将选项SetType映射到数组,swift,Swift,鉴于以下情况: struct Weekdays: OptionSetType { let rawValue: Int init(rawValue: Int) { self.rawValue = rawValue } static let Monday = Weekdays(rawValue: 1) static let Tuesday = Weekdays(rawValue: 2) static let Wednesday = Weekdays(raw

鉴于以下情况:

struct Weekdays: OptionSetType {

    let rawValue: Int
    init(rawValue: Int) { self.rawValue = rawValue }

    static let Monday = Weekdays(rawValue: 1)
    static let Tuesday = Weekdays(rawValue: 2)
    static let Wednesday = Weekdays(rawValue: 4)
    static let Thursday = Weekdays(rawValue: 8)

    static let allOptions: [Weekdays] = [.Monday, .Tuesday, .Wednesday, .Thursday]

}
通过执行以下操作,我可以将
整数数组
转换为
工作日
对象:

let arr = [1, 4]
let weekdays = arr.reduce(Weekdays()) { $0.union(Weekdays(rawValue: $1)) }

我的问题是,我如何将一个
平日
对象转换成一个
整数数组

当我写这个问题时,我发现:

let array = Weekdays.allOptions.filter { weekdays.contains($0) }.map { $0.rawValue }
有更好的方法吗?

(不一定更好,但用不同的方法来看待它,并稍微 (更一般)

OptionSetType
继承自
RawRepresentable
,因此可以 从关联的原始类型转换为关联的原始类型,在您的示例中是
Int

因此,“缺失链接”是原始值之间的转换(例如
5
) 以及位分量的整数数组(例如
[1,4]

这可以通过
Int
扩展方法完成:

extension Int {
    init(bitComponents : [Int]) {
        self = bitComponents.reduce(0, combine: (+))
    }

    func bitComponents() -> [Int] {
        return (0 ..< 8*sizeof(Int)).map( { 1 << $0 }).filter( { self & $0 != 0 } )
    }
}
和反向转换

let array = weekdays.rawValue.bitComponents()
print(array)
// [1, 4]
优点:

  • 不需要明确定义
    allOptions:
  • 它可以应用于其他选项集类型(具有
    Int
    作为原始值)
还可以尝试将转换定义为协议扩展, e、 g.
IntegerType
,因此同样适用于其他整数原始类型。然而,这似乎有点复杂/丑陋
因为左移位运算符
不能准确回答问题,但可能对其他人有用。根据Martin的回答,我提取了组件对象:

extension FixedWidthInteger {
    init(bitComponents : [Self]) {
        self = bitComponents.reduce(0, +)
    }

    var bitComponents : [Self] {
        (0 ..< Self.bitWidth).map { 1 << $0 } .filter { self & $0 != 0 }
    }
}

extension OptionSet where RawValue: FixedWidthInteger, Self == Self.Element {
    var components : [Self] { rawValue.bitComponents.map(Self.init) }
}
扩展名FixedWidthInteger{
初始化(位组件:[Self]){
self=bitComponents.reduce(0,+)
}
变量bitComponents:[自身]{

(0..OptionSet
上定义扩展来改进扩展的上下文

扩展选项起始,其中RawValue:UnsignedInteger{
var individualCases:[自身]{

返回(0..我喜欢这样一个事实,即不再需要Alloption。不过,我的解决方案比这个解决方案有一个优势…我的解决方案可以创建任何类型的数组,而不仅仅是rawValue类型。在我的实际用例中,我将从
选项集类型
映射到
字符串
的数组。也就是说,您的答案涵盖了具体的用例这个问题我回答得很好!谢谢。
extension Int {
    init(bitComponents : [Int]) {
        self = bitComponents.reduce(0, +)
    }

    func bitComponents() -> [Int] {
        return (0 ..< 8*MemoryLayout<Int>.size).map( { 1 << $0 }).filter( { self & $0 != 0 } )
    }
}
extension FixedWidthInteger {
    init(bitComponents : [Self]) {
        self = bitComponents.reduce(0, +)
    }

    var bitComponents : [Self] {
        (0 ..< Self.bitWidth).map { 1 << $0 } .filter { self & $0 != 0 }
    }
}

extension OptionSet where RawValue: FixedWidthInteger, Self == Self.Element {
    var components : [Self] { rawValue.bitComponents.map(Self.init) }
}