2012-06-08 88 views
1

我目前正在嘗試學習erlang,而我正在嘗試做的是對存儲在位數組或int中的數組的特定索引執行操作。如果某個位置有0,則不使用該位置的數組索引。Erlang位索引

所以設想如下:

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圍繞位串有特殊的語法(類似於< < >>),那麼有沒有一種有效的方式來索引位數組以獲得指示?

回答

1

大部分時間,Erlang使用列表和遞歸,所以我認爲它是單獨通過每一位而不是嘗試以迭代方式索引每一位的慣用方法。

The documentation on how to work with bitstrings is here.爲了創建數字21的位串,我們可以寫<<21>>。由於二進制成員的默認類型是整數,並且整數的默認大小是8,因此它將產生一個類似於00010101的位串。如果你想具體得到一個值的最後N個字節是<<Value:N>>。爲了得到21的最後5位,我們可以說<<21:5>>這將產生。

我寫了下面模塊做你想做什麼:

-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] 
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). 

我敢肯定,這將是非常好的一個列表理解了。作爲讀者的練習:)