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

(我现在这不是尾递归——想保持简单,此外在较新的 Erlang 版本中性能并不重要)

示例输出:

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

但是如果 Size 不是以下的倍数,这会留下最后一个块byte_site(P)

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

3 回答 3

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].
于 2011-05-04T09:17:36.130 回答
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 >> ]

然后从最后一段中切掉多余的位..

于 2011-05-04T09:31:11.950 回答
2

您的原始版本的变体可能更有效:

split_packet(Size, Data) when Size > 0 ->
    case Data of
        <<Packet:Size/binary, Rest/binary>> ->
            [Packet | split_packet(Size, Rest)];
        <<>> ->
            [];
        _ ->
            [Data]
    end.
于 2011-05-04T19:36:43.287 回答