我正在尝试实现类似二进制掩码的功能,其中将一个Int转换为其组成的数组(2的幂),例如:
69 = [64, 4, 1]
我不想使用二进制掩码和移位,因为我想对界面元素使用Swift枚举:
enum State: Int{
case readyButton = 1
case workingButton = 2
case sleepingButton = 4
//etc
}
then 7 = [.sleepingButton, .workingButton, .readyButton] // 7 = 4+2+1
Swift中有一些内置工具可以帮助我将Int转换为2个组件的力量吗?
答案 0 :(得分:2)
您可能正在寻找类似的东西。在编写时,如果值不匹配,它将崩溃,但是您可以根据需要对其进行调整。尽管它确实使用了shift,但是它仍然可以很好地转换为您的枚举。
extension UInt32 {
func state() -> [State] {
var bitvals: [UInt32] = []
var mask: UInt32 = 1
while mask > 0 {
if mask & self > 0 {
bitvals.append(mask)
}
mask = mask << 1
}
let state = bitvals.map { State(rawValue: $0)! }
return state
}
}
enum State: UInt32 {
case readyButton = 1
case workingButton = 2
case sleepingButton = 4
}
let val: UInt32 = 7
print(val.state())
这将打印出您在问题末尾给出的示例。
答案 1 :(得分:1)
更新后的答案,将任何Int转换为2的幂的数组。如果您希望它崩溃为负值,则取消注释致命错误
enum State: Int {
case illegal = -1
case readyButton = 1
case workingButton = 2
case sleepingButton = 4
}
这是将整数分解为2的幂的一般解决方案:
extension Int {
func toPowersOf2() -> [Int] {
guard self > 0 else {
// fatalError("The number should be strictly positive")
print("The number should be strictly positive")
return [-1] //not really - use fatal error above to enforce crash if you don't want this behavior
}
var arrayOfPowers: [Int] = [] //Will hold the desired powers
var remainder: Int = self //We will substract found powers from the original number
//Since Ints are coded on 64 bits (the 64th is for the sign)
//Let's create an array of all the powers of 2 that
//could be used to decompose an integer
let powers = (0...62).map { NSDecimalNumber(decimal: pow(2.0, $0)).intValue }
//Let's go from the highest to the lowest power
for i in (0 ..< powers.count).reversed() {
//Here we are looking for the power just smaller than the remainder
if i < powers.count - 1, powers[i] <= remainder, powers[i + 1] > remainder {
let p = powers[i]
arrayOfPowers.append(p)
remainder -= p
}
//if this is the biggest power and it is smaller than the number, then add it to arrayOfPowers
else if i == powers.count - 1, powers[i] <= remainder {
let p = powers[i]
arrayOfPowers.append(p)
}
}
return arrayOfPowers
}
func toStateArray() -> [State] {
let array = self.toPowersOf2().map{ State(rawValue: $0) }.filter{ $0 != nil }
return array as! [State]
}
}
您可以像这样使用它:
(-1).toStateArray()//[illegal]
0.toStateArray() //[illegal]
7.toPowersOf2() //[4, 2, 1]
7.toStateArray() //[sleepingButton, workingButton, readyButton]