我正在尝试将较大的[UInt8]
重新映射为[UInt16]
,到目前为止,我的解决方案如下:
//Function that converts [UInt8] into [UInt16]
func foo(arr: [UInt8])->[UInt16]{
//Split into even and odds
let even = stride(from: 0, to: arr.count, by: 2).map { arr[$0] }
let odd = stride(from: 1, to: arr.count, by: 2).map { arr[$0] }
//pair each even with the next odd
let paired=Array(zip(even, odd))
//reduce UInt8 pairs to UInt16
return paired.reduce([UInt16]()) { (acc, curr) -> [UInt16] in
let u16 = UnsafePointer([curr.0, curr.1]).withMemoryRebound(to: UInt16.self, capacity: 1) {
$0.pointee
}
var newV = acc
newV.append(u16)
return newV
}
}
以上方法有效,但是效率很低。减少功能是大部分计算时间发生的地方。
我想知道是否可以直接使用UnsafePointer.withMemoryRebound
重映射。
我尝试过:
let test : [UInt16] = UnsafePointer([UInt8(0), UInt8(1),UInt8(0), UInt8(1)]).withMemoryRebound(to: [UInt16].self, capacity: 2) {
$0.pointee
}
导致:
Execution interrupted. Enter code to recover and continue.
Enter LLDB commands to investigate (type :help for assistance.)
Process 57635 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x00007fff7d038d5f libobjc.A.dylib`objc_retain + 15
libobjc.A.dylib`objc_retain:
-> 0x7fff7d038d5f <+15>: movq (%rdi), %rax
0x7fff7d038d62 <+18>: movabsq $0x7ffffffffff8, %rcx ; imm = 0x7FFFFFFFFFF8
0x7fff7d038d6c <+28>: andq %rax, %rcx
0x7fff7d038d6f <+31>: testb $0x2, 0x20(%rcx)
Target 0: (repl_swift) stopped.
也许我误解了它应该如何工作。能做到吗有更好的方法吗?
答案 0 :(得分:1)
我的建议是创建一个Data
实例,并使用withUnsafeBytes
重新映射字节。
let arr : [UInt8] = [0x31, 0x32, 0x33, 0x34]
let data = Data(arr)
let u16 = data.withUnsafeBytes {
[UInt16](UnsafeBufferPointer(start: $0, count: data.count/MemoryLayout<UInt16>.stride))
} // [12849, 13363]
答案 1 :(得分:0)
使用withUnsafeBytes()
方法访问数组的元素存储,该方法使用UnsafeRawBufferPointer
调用闭包。现在可以将该指针 bound 绑定到所需类型UInt16
的缓冲区指针。最终创建了新的阵列-这是唯一复制数据的地方。
let uint8Array: [UInt8] = [1, 2, 3, 4]
let uint16Array = uint8Array.withUnsafeBytes { ptr in
Array(ptr.bindMemory(to: UInt16.self))
}
print(uint16Array) // [513, 1027]