1

我目前正在尝试学习erlang,我想做的是对存储在位数组或int中的数组的特定索引执行操作。如果某个位置有 0,则不使用该位置的数组索引。

因此,设想以下内容:

Example the array is: [1, 3, 5, 42, 23]
My bit array is: 21 = 10101 in binary
so I'm using indicies 1,3,5
so I'm calling a function on [1, 5, 23]

我的功能是形式

my_function(Array, BitArray) ->
    SubArray = get_subarray_from_bitarray(Array, BitArray),
    process_subarray(SubArray).

我需要有关 get_subarray_from_bitarray() 的帮助。我知道 erlang 对位字符串有特殊的语法(类似于 <<>>),所以有没有一种有效的方法来索引位数组以获取索引?

4

2 回答 2

1

大多数时候,Erlang 使用列表和递归,所以我认为单独遍历每个位而不是尝试以迭代方式索引每个位是惯用的。

关于如何使用位串的文档在这里。 为了从数字 21 创建一个位串,我们可以写<<21>>. 由于二进制成员的默认类型是整数,而整数的默认大小是 8,它将产生一个看起来像00010101. 如果要专门获取一个值的最后 N 个字节是<<Value:N>>. 为了得到 21 的最后 5 位,我们可以说<<21:5>>哪个会产生10101.

我写了以下模块来做你想做的事:

-module(bitmask).
-export([get_subarray_from_bitarray/2]).

get_subarray_from_bitarray(Bitstring, List) ->
  get_subarray_from_bitarray_loop(Bitstring, List, []).

get_subarray_from_bitarray_loop(_Bits, [], Gathered) ->
  io:format("End of list~n", []),
  lists:reverse(Gathered);
get_subarray_from_bitarray_loop(<<>>, _Others, Gathered) ->
  io:format("End of bitstring~n", []),
  lists:reverse(Gathered);
get_subarray_from_bitarray_loop(<<Bit:1, Rest/bitstring>>, [Item | Others], Gathered) ->
  io:format("Bit: ~w ~n", [Bit]),
  case Bit of
    1 -> get_subarray_from_bitarray_loop(Rest, Others, [Item | Gathered]);
    0 -> get_subarray_from_bitarray_loop(Rest, Others, Gathered)
  end.

当列表中的位或项用完时,前 2 个子句将返回最终列表。重要的位语法在最后一个子句的开头,<<Bit:1, Rest/bitstring>>. 这将值设置为Bit位串中第一位的值,以及位串Rest的其余部分。根据 Bit 的值,我们决定是否将当前项目添加到列表中。

下面的示例调用:

> bitmask:get_subarray_from_bitarray(<<21:5>>, [1, 3, 5, 42, 23]).   
Bit: 1 
Bit: 0 
Bit: 1 
Bit: 0 
Bit: 1 
End of list
[1,5,23]
> bitmask:get_subarray_from_bitarray(<<31>>, [1, 3, 5, 42, 23]).  
Bit: 0 
Bit: 0 
Bit: 0 
Bit: 1 
Bit: 1 
End of list
[42,23]
> bitmask:get_subarray_from_bitarray(<<5:3>>, [1, 3, 5, 42, 23]). 
Bit: 1 
Bit: 0 
Bit: 1 
End of bitstring
[1,5]
于 2012-06-09T03:19:51.280 回答
0

该功能的可能实现get_subarray_from_bitarray/2可能是:

get_subarray_from_bitarray(Array, BitArray) ->
    gsb(Array, BitArray, []).

gsb(_, 0, R) -> lists:reverse(R);
gsb([A1|A2], B, R) ->
  NextR = if B band 1 /= 0 ->
     [A1|R];
  true ->
     R
  end,
  gsb(A2, B div 2, NextR).

我很确定列表理解也会非常好。留给读者作为练习:)

于 2012-06-08T22:36:56.650 回答