Today’s Erlang Thursday is lists:zip/2.
lists:zip/2
returns a new list of two-tuples, from the corresponding elements of the two lists passed as arguments.
1 2 3 4 5 6 | lists:zip ([a, b, c, d], [1, 2, 3, 4]). % [{a,1},{b,2},{c,3},{d,4}] lists:zip ([a, b, c, d], [{1, 3}, {2, 5}, {3, 7}, {4, 11}]). % [{a,{1,3}},{b,{2,5}},{c,{3,7}},{d,{4,11}}] lists:zip ([a, b], [ fun lists:map /3, fun lists:foldl /3]). % [{a,#Fun<lists.map.3>},{b,#Fun<lists.foldl.3>}] |
If the lists are not of the same length a function clause match exception is thrown.
1 2 3 4 5 6 7 8 | lists:zip ([a, b, c, d], [1, 2, 3]). % ** exception error: no function clause matching lists:zip([d],[]) (lists.erl, line 385) % in function lists:zip/2 (lists.erl, line 385) % in call from lists:zip/2 (lists.erl, line 385) lists:zip ([a, b, c], [1, 2, 3, 4]). % ** exception error: no function clause matching lists:zip([],[4]) (lists.erl, line 385) % in function lists:zip/2 (lists.erl, line 385) % in call from lists:zip/2 (lists.erl, line 385) |
There is also a 3-arity version of the zip function lists:zip3/3, which behaves like lists:zip/2
but takes three lists as arguments instead of two.
1 2 | lists:zip3 ([a, b, c, d], [1, 2, 3, 4], [ "alpha" , "bravo" , "charlie" , "delta" ]). % [{a,1,"alpha"},{b,2,"bravo"},{c,3,"charlie"},{d,4,"delta"}] |
If you need to combine the arguments in a different manner, you can use lists:zipwith/3, or lists:zipwith3/4, each of which takes as the first argument a 2-arity combining function.
1 2 3 4 5 6 7 8 9 10 11 | lists:zipwith ( fun (X, Y) -> X * Y end , [1, 2, 3, 4], [2, 3, 4, 5]). % [2,6,12,20] lists:zipwith ( fun (X, Y) -> X + Y end , [1, 2, 3, 4], [2, 3, 4, 5]). % [3,5,7,9] lists:zipwith3 ( fun (X, Y, Z) -> X * Y * Z end , [1, 2, 3, 4], [2, 3, 4, 5], [4, 3, 2, 1]). % [8,18,24,20] lists:zipwith3 ( fun (X, Y, Z) -> {{X, Y}, Z} end , [a, b, c, d], [1, 2, 3, 4], [ "alpha" , "bravo" , "charlie" , "delta" ]). % [{{a,1},"alpha"}, % {{b,2},"bravo"}, % {{c,3},"charlie"}, % {{d,4},"delta"}] |
–Proctor