Erlang位索引

时间:2012-06-08 22:16:30

标签: list binary erlang bitmask bitstring

我目前正在尝试学习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有关于位串的特殊语法(类似于<<>>),所以有没有一种有效的方法可以索引到位数组中以获得指示?

2 个答案:

答案 0 :(得分:1)

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

The documentation on how to work with bitstrings is here.为了从数字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的值设置为bitstring中第一位的值,将Rest的值设置为bitstring的其余位。根据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]

答案 1 :(得分: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).

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