数组 – Swift位数组到字节数组(UInt8数组)
我有位数组:
var bits: [Bit] 以及如何将其转换为字节数组: var bytes: [UInt8] 例如,我有280位,我应该有35个UInt8字节数组.我可以想到解决方案,我拿8位并检查第一个是否为真,如果第二个为真,那么总和结果并有价值.我会为我的位数组中的每8位做一次.但我认为这将是一个糟糕的解决方案(它可以工作,但有不必要的计算).我认为可能有更快的解决方案,有一些转移,所以但我真的很糟糕,所以我正在寻求帮助.谢谢
一种可能的解决方案是枚举数组中的所有位
并且对于所有“One”位设置UInt8中的相应位 数组: func bitsToBytes(bits: [Bit]) -> [UInt8] { let numBits = bits.count let numBytes = (numBits + 7)/8 var bytes = [UInt8](count : numBytes,repeatedValue : 0) for (index,bit) in enumerate(bits) { if bit == .One { bytes[index / 8] += 1 << (7 - index % 8) } } return bytes } 主要思想是对于位数组中的给定索引, 例: // 0110 0100 0000 1001 let bits : [Bit] = [.Zero,.One,.Zero,.One] let bytes = bitsToBytes(bits) println(bytes) // [100,9] 或者,您可以“内联”每个组的计算 func bitsToBytes(bits: [Bit]) -> [UInt8] { let numBits = bits.count let numBytes = numBits/8 var bytes = [UInt8](count : numBytes,repeatedValue : 0) for pos in 0 ..< numBytes { let val = 128 * bits[8 * pos].toIntMax() + 64 * bits[8 * pos + 1].toIntMax() + 32 * bits[8 * pos + 2].toIntMax() + 16 * bits[8 * pos + 3].toIntMax() + 8 * bits[8 * pos + 4].toIntMax() + 4 * bits[8 * pos + 5].toIntMax() + 2 * bits[8 * pos + 6].toIntMax() + 1 * bits[8 * pos + 7].toIntMax() bytes[pos] = UInt8(val) } return bytes } 这里,为简单起见,如果位数不是8的倍数,则忽略任何多余的位.相同的代码也可以写一点 func bitsToBytes(bits: [Bit]) -> [UInt8] { return map(0 ..< bits.count/8) { pos in let val = 128 * bits[8 * pos].toIntMax() + 64 * bits[8 * pos + 1].toIntMax() + 32 * bits[8 * pos + 2].toIntMax() + 16 * bits[8 * pos + 3].toIntMax() + 8 * bits[8 * pos + 4].toIntMax() + 4 * bits[8 * pos + 5].toIntMax() + 2 * bits[8 * pos + 6].toIntMax() + 1 * bits[8 * pos + 7].toIntMax() return (UInt8(val)) } } 基准:现在是一个快速而肮脏的基准测试应用程序(下面的代码),比较各种解决方案. Swift 1.1 / Xcode 6.2(6C131e)的结果: Martin1: 0.0460730195045471 Martin2: 0.0280380249023438 Martin3: 0.0374950170516968 Antonio: 5.85363000631332 Nate : 4.86936402320862 Swift 1.2 / Xcode 6.3(6D532l)的结果: Martin1: 0.0228430032730103 Martin2: 0.00573796033859253 Martin3: 0.00732702016830444 Antonio: 0.515677988529205 Nate : 0.634827971458435 码: protocol BitsToBytesConverter { var ident : String { get } func bitsToBytes(bits: [Bit]) -> [UInt8] } class MR1 : BitsToBytesConverter { let ident = "Martin1" func bitsToBytes(bits: [Bit]) -> [UInt8] { let numBits = bits.count let numBytes = (numBits + 7)/8 var bytes = [UInt8](count : numBytes,repeatedValue : 0) for (index,bit) in enumerate(bits) { if bit == .One { bytes[index / 8] += UInt8(1 << (7 - index % 8)) } } return bytes } } class MR2 : BitsToBytesConverter { let ident = "Martin2" func bitsToBytes(bits: [Bit]) -> [UInt8] { let numBits = bits.count let numBytes = numBits/8 var bytes = [UInt8](count : numBytes,repeatedValue : 0) for pos in 0 ..< numBytes { let val = 128 * bits[8 * pos].toIntMax() + 64 * bits[8 * pos + 1].toIntMax() + 32 * bits[8 * pos + 2].toIntMax() + 16 * bits[8 * pos + 3].toIntMax() + 8 * bits[8 * pos + 4].toIntMax() + 4 * bits[8 * pos + 5].toIntMax() + 2 * bits[8 * pos + 6].toIntMax() + 1 * bits[8 * pos + 7].toIntMax() bytes[pos] = UInt8(val) } return bytes } } class MR3 : BitsToBytesConverter { let ident = "Martin3" func bitsToBytes(bits: [Bit]) -> [UInt8] { return map(0 ..< bits.count/8) { pos in let val = 128 * bits[8 * pos].toIntMax() + 64 * bits[8 * pos + 1].toIntMax() + 32 * bits[8 * pos + 2].toIntMax() + 16 * bits[8 * pos + 3].toIntMax() + 8 * bits[8 * pos + 4].toIntMax() + 4 * bits[8 * pos + 5].toIntMax() + 2 * bits[8 * pos + 6].toIntMax() + 1 * bits[8 * pos + 7].toIntMax() return (UInt8(val)) } } } class AB : BitsToBytesConverter { let ident = "Antonio" typealias IntegerType = UInt8 func bitsToBytes(bits: [Bit]) -> [UInt8] { let initial = [IntegerType]() return reduce(enumerate(bits),initial) { array,element in // The size in bits of a UInt8 let size = sizeof(IntegerType) * 8 // Create a mutable copy of the array returned at the previous iteration var next = array // If it's the first iteration,or an iteration divisible by the size of UInt8,// append a new element to the array if element.index % size == 0 { next.append(0x00) } // Shift all bits of the last element to the left next[next.count - 1] <<= 1 // If the current bit is one,add 1 to the rightmost bit // Using a logical OR if element.element == .One { next[next.count - 1] |= 0x01 } return next } } } class NC : BitsToBytesConverter { let ident = "Nate " func group<T>(array: [T],byCount groupCount: Int) -> [Slice<T>] { // get a list of the start indices let startIndices = stride(from: 0,to: array.count,by: groupCount) // add `groupCount` to each to get the end indices let endIndices = lazy(startIndices).map { advance($0,groupCount,array.count) } // zip those together & map onto an array of slices of the input array return map(Zip2(startIndices,endIndices)) { array[$0.0 ..< $0.1] } } func bitsToByte(bits: Slice<Bit>) -> UInt8 { return bits.reduce(0) { accumulated,current in accumulated << 1 | (current == .One ? 1 : 0) } } func bitsToBytes(bits: [Bit]) -> [UInt8] { return group(bits,byCount: 8).map(bitsToByte) } } let numBits = 256 // Bits per bit array let numBitArrays = 10000 // Number of bit arrays func randomBits() -> [Bit] { return map(0 ..< numBits) { _ in Bit(rawValue: Int(arc4random_uniform(2)))! } } func randomBitsArray() -> [[Bit]] { return map(0 ..< numBitArrays) { _ in randomBits() } } let bitsArray = randomBitsArray() func test(conv : BitsToBytesConverter) { let x = conv.bitsToBytes([]) let startTime = NSDate() for bits in bitsArray { let bytes = conv.bitsToBytes(bits) } let duration = -startTime.timeIntervalSinceNow println("(conv.ident): (duration)") } test(MR1()) test(MR2()) test(MR3()) test(AB()) test(NC()) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- SQLite3.c中的一个bug:error: expected value in expressio
- ios – 错误ITMS-90717:“无效的App Store图标”
- ajax – 为什么这个跨域请求在其他浏览器中工作但在IE9中不
- XML中的方法总结
- c# – WPF模板和GridView中的DataContext绑定
- 正则表达式 – 正则表达式在记事本中将字符串的开头移动到结
- c# – 动态初始化窗体对象
- c# – 是否只能在自动实现的属性的Setter上设置属性?
- c – 使用reinterpret_cast将std :: vector中的数据重新整形
- SSH2下使用ajaxFileUpload控件上传附件