2011-05-04 51 views
2

我想要的東西更優雅,以取代以下功能:更好的辦法來分割成塊的二進制,最好有位串內涵

split_packet(_, <<>>) -> 
    []; 
split_packet(Size, P) when byte_size(P) < Size -> 
    [ P ]; 
split_packet(Size, P) -> 
    {Chunk, Rest} = split_binary(P, Size), 
    [ Chunk | split_packet(Size, Rest) ]. 

(我現在這不是尾遞歸 - 想保持它簡單,除了沒關係在新版本二郎性能明智)

輸出示例:

1> split_packet(3, <<1,2,3,4,5,6,7,8>>). 
[<<1,2,3>>,<<4,5,6>>,<<7,8>>] 

與列表理解優雅的解決方案是最好因爲這樣做的結果是進一步處理列表理解,然後可以包裝在一個理解。

我試圖

[ X || <<X:Size/binary>> <= P ]. 

但是如果大小不是byte_site(P)多這留下了最後一塊:

2> [ X || <<X:3/binary>> <= <<1,2,3,4,5,6,7,8>> ]. 
[<<1,2,3>>,<<4,5,6>>] 

回答

4

坦率地說,我看不出有任何問題與您的當前版本。正如你所說的,你不能用二進制/列表理解來做,因爲最後的片段將被丟棄。

我能想到的唯一的事情是重新排序的條款,最常見的情況下,第一個匹配:

split_packet(Size, P) when byte_size(P) >= Size-> 
    {Chunk, Rest} = split_binary(P, Size), 
    [Chunk|split_packet(Size, Rest)]; 
split_packet(_Size, <<>>) -> 
    []; 
split_packet(_Size, P) -> 
    [P]. 
+1

好的,謝謝。我曾希望用二進制匹配的一個很好的技巧,逃脫我可以做一個很好的一個襯墊出來。 – 2011-05-04 12:52:24

+0

最後一個'split_packet/2'聲明中的'Size'參數沒有被使用,所以它應該被替換爲'_'或者前綴'_'。 – 2015-09-05 14:54:16

+0

@KristinnÖrnSigurðsson謝謝,我把它清理了一下。 – 2015-09-07 08:25:53

2

你可能墊(Size - (byte_size(Binary) rem Size)) * 8輸入的二進制,運行它通過你的列表中理解[ X || <<X:Size/binary>> <= P ]

Y = (Size - (byte_size(Binary) rem Size)) * 8

[ X || <<X:3/binary>> <= << Binary/binary , 0:Y >> ]

,然後從上段斬額外的比特..

+1

像這樣的變通辦法以某種方式擊敗了列表理解的原因 - 優雅和簡短,並且它會慢慢先填充二進制文件並將其從最後一個塊中刪除。除了我更願意做'{A,R} = split_binary(byte_size(P)div Size)* Size),[X || << X:Size/binary >><= A] ++ R',但不認爲這是優雅的。特別是因爲我不能在相同理解的情況下做其他操作,因爲我需要特殊處理最後的塊。 – 2011-05-04 13:02:23

1

,可能是多一點效率原件的變化:

split_packet(Size, Data) when Size > 0 -> 
    case Data of 
     <<Packet:Size/binary, Rest/binary>> -> 
      [Packet | split_packet(Size, Rest)]; 
     <<>> -> 
      []; 
     _ -> 
      [Data] 
    end.