大多数时候,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]