tags:

views:

120

answers:

4

Whats the easy/efficient way of interleaving three data sets..

Data1 = [<<5>>,<<6>>,<<7>>],
Data2 = [<<5>>,<<6>>,<<7>>],
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]]
+2  A: 

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.

Manoj Govindan
You could also use lists:zipwith3 to avoid writing the recursive loop yourself.
cthulahoops
@cthulahoops: You'll notice that I did mention `lists:zip3`. However the OP wanted a list of lists rather than the list of tuples that `zip3` produces. Hence rolled my own function. I am sure you can convert the tuples to lists though.
Manoj Govindan
I was thinking of lists:zipwith3(fun(X, Y, Z) -> [X, Y, Z] end, Data1, Data2, Data3)) which deals with the tuple/list issue.
cthulahoops
@cthulahoops: of course you were. My eyesight is getting sketchy with age. Mea culpa.
Manoj Govindan
A: 
Final = Data1 ++ Data2 ++ Data3.
ram
I don't think the OP wants to _concatenate_ lists. The code fragment you have posted will produce `[<<5>>,<<6>>,<<7>>,<<5>>,<<6>>,<<7>>,<<5>>,<<6>>,<<7>>]` which is not what he expects `Final` to be.
Manoj Govindan
Ah! You're right. I totally missed the interleaving part.
ram
+2  A: 

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>>]
Hynek -Pichi- Vychodil
Thanks that works like a charm
A: 

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.

Jimmy Ruska