Erlang - Interleave the easy way
Whats the easy/efficient way of interleaving three data sets..
Data1 = [<<5>>,<<6>>,<<7>>],
Data2 = [<<5>>,<<6>>,<<7>&g开发者_开发百科t;],
Data3 = [<<5>>,<<6>>,<<7>>].
End Result:
Final = [<<5>>, <<5>>, <<5>>, <<6>>, <<6>>, <<6>>, <<7>>, <<7>>, <<7>>]
Im sure its like
[X || X <- [Data1, Data2, Data3]]
Module function:
zip3(X, Y, Z) when X =:= []; Y =:= []; Z =:= [] -> [];
zip3([HX | TX], [HY | TY], [HZ | TZ]) -> [ HX, HY, HZ | zip3(TX, TY, TZ)].
Same in shell:
F = fun(D1, D2, D3) ->
G = fun(F, X, Y, Z) when X =:= []; Y =:= []; Z =:= [] -> [];
(F, [HX | TX], [HY | TY], [HZ | TZ]) -> [ HX, HY, HZ | F(F, TX, TY, TZ)]
end,
G(G, D1, D2, D3)
end,
Data1 = [<<5>>,<<6>>,<<7>>],
Data2 = [<<5>>,<<6>>,<<7>>],
Data3 = [<<5>>,<<6>>,<<7>>],
F(Data1, Data2, Data3).
[<<5>>,<<5>>,<<5>>,<<6>>,<<6>>,<<6>>,<<7>>,<<7>>,<<7>>]
And of course you can do it with lists
module:
lists:append(lists:zipwith3(fun(X, Y, Z) -> [X, Y, Z] end, Data1, Data2, Data3)).
[<<5>>,<<5>>,<<5>>,<<6>>,<<6>>,<<6>>,<<7>>,<<7>>,<<7>>]
You can write a custom zip
function to accomplish this.
zip([HX | TX], [HY | TY], [HZ | TZ]) -> [[HX, HY, HZ] | zip(TX, TY, TZ)];
zip([], [], []) -> [].
This function will work fine as long as the length of the inputs are the same. Dealing with inputs of varying length will take some tinkering. Something like this:
zip(X, Y, Z) when length(X) =:= 0; length(Y) =:= 0; length(Z) =:= 0 -> [];
zip([HX | TX], [HY | TY], [HZ | TZ]) -> [[HX, HY, HZ] | zip(TX, TY, TZ)].
Call it thus:
7> my_module:zip(Data1, Data2, Data3).
[[<<5>>,<<5>>,<<5>>],
[<<6>>,<<6>>,<<6>>],
[<<7>>,<<7>>,<<7>>]]
See also: standard library function lists:zip3
.
Final = Data1 ++ Data2 ++ Data3.
Here's my go at it. With this you can add as many Data sets as you want, just add them to a list. It also takes into account if the lists are different sizes. Probably more efficient to use the new binary module instead of breaking down the binary data into 1 byte lists if the binary data can be large or it's a very common function.
-module(zippy).
-compile(export_all).
zipAll(L) -> zip({L,[]}).
zip({L,Final}) ->
case lists:any(fun(X) -> case X of [] -> false; _ -> true end end,L) of
true -> zip(lists:mapfoldl(fun x/2,Final,L));
_ -> lists:reverse(Final)
end.
x([],L) -> {[],[null|L]};
x([H|T],L) -> {T,[H|L]}.
start() ->
Data1 = [<<5>>,<<6>>,<<7>>],
Data2 = [<<5>>,<<6>>,<<7>>],
Data3 = [<<5>>,<<6>>,<<7>>],
Data4 = [<<5>>,<<6>>,<<7>>,<<1>>],
zipAll([Data1,Data2,Data3,Data4]).
you're thinking of list comprehensions [{X,Y,Z} || X <-Data1, Y<-Data2,Z<- Data3]] which is more to generate all possibilities where order doesn't matter.
精彩评论