我有带位的数组:
var bits: [Bit]
以及如何将其转换为字节数组:
var bytes: [UInt8]
例如,我有 280 位,我应该有 35 个 UInt8 字节数组。我可以想到解决方案,我采用 8 位并检查第一个是否为真,第二个是否为真等等并对结果求和并具有值(value)。我会为我的位数组中的每 8 位执行此操作。但我认为这将是一个糟糕的解决方案(它可以工作,但需要进行不必要的计算)。我认为可能会有更快的解决方案,但我在这方面真的很糟糕,所以我正在寻求帮助。谢谢
最佳答案
一个可能的解决方案是枚举数组中的所有位
并为所有“一”位设置 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
}
主要思想是对于位数组中给定的index,
index/8是字节数组中对应的索引,
index % 8 是字节中的位位置。你可以
使用 index % 8 或 7 - index % 8 作为偏移量,具体取决于
所需的位顺序。
例子:
// 0110 0100 0000 1001
let bits : [Bit] = [.Zero, .One, .One, .Zero, .Zero, .One, .Zero, .Zero, .Zero, .Zero, .Zero, .Zero, .One, .Zero, .Zero, .One]
let bytes = bitsToBytes(bits)
println(bytes) // [100, 9]
或者,您可以“内联”每个组的计算 的 8 位。您必须检查哪种解决方案性能更好 在你的情况下。
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))
}
}
基准测试:现在这是一个快速而简单的基准测试应用程序(代码如下),比较了各种解决方案。 它测量转换 10,000 个长度为 256 的位数组的时间。 测试是在 MacBook Pro 2.3 GHz Intel Core i7 上完成的, 以及使用“发布”配置编译的代码。
Swift 1.1/Xcode 6.2 (6C131e) 的结果:
Martin1: 0.0460730195045471 Martin2: 0.0280380249023438 Martin3: 0.0374950170516968 Antonio: 5.85363000631332 Nate : 4.86936402320862
Results with Swift 1.2/Xcode 6.3 (6D532l):
Martin1: 0.0228430032730103 Martin2: 0.00573796033859253 Martin3: 0.00732702016830444 Antonio: 0.515677988529205 Nate : 0.634827971458435
Code:
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())
关于arrays - Swift 位数组到字节数组(UInt8 数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28929804/
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby数组,我们在StackOverflow上找到一
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
通过rubykoans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>