DogEatDog
DogEatDog

Reputation: 3037

Elixir - Merge 2 List of Lists (like columns)

How do you merge two arrays together in Elixir using the Enum function?

E.g.

  points  = [[1.0, 2.0],
              [5.0, 3.0],
              [2.0, 4.0],
              [3.0, 1.0],
              [2.0, 2.0],
              [4.0, 3.0],
              [1.0, 2.0],
              [2.0, 5.0],
              [14.0, 13.0],
              [11.0, 12.0],
              [12.0, 15.0],
              [32.0, 25.0]]

    results  = [1.0,
                3.0,
                2.0,
                1.0,
                3.0,
                2.0,
                1.0,
                3.0,
                2.0,
                1.0,
                3.0,
                2.0]

The combined arrays (column added), should look like this:

    combined =  [[1.0, 2.0, 1.0],
                [5.0, 3.0, 3.0],
                [2.0, 4.0, 2.0],
                [3.0, 1.0, 1.0],
                [2.0, 2.0, 3.0],
                [4.0, 3.0, 2.0],
                [1.0, 2.0, 1.0],
                [2.0, 5.0, 3.0],
                [14.0, 13.0, 2.0],
                [11.0, 12.0, 1.0],
                [12.0, 15.0, 3.0],
                [32.0, 25.0, 2.0]]       

It seems like something like this should work:

points
  |> Stream.with_index
  |> Enum.map(fn({x,i}) -> Enum.into(x, Enum.fetch!(results, i)) end)                

Although, this produces an error:

** (Protocol.UndefinedError) protocol Collectable not implemented for 1.0. This protocol is implemented for: BitString, Ecto.Adapters.SQL.Stream, File.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Plug.Conn, Postgrex.Stream
    (elixir) lib/collectable.ex:1: Collectable.impl_for!/1
    (elixir) lib/collectable.ex:77: Collectable.into/1
    (elixir) lib/enum.ex:1158: Enum.into_protocol/2
    (elixir) lib/enum.ex:1259: anonymous fn/3 in Enum.map/2
    (elixir) lib/enum.ex:1824: anonymous fn/3 in Enum.map/2
    (elixir) lib/stream.ex:1413: anonymous fn/3 in Enumerable.Stream.reduce/3
    (elixir) lib/stream.ex:978: anonymous fn/3 in Stream.with_index/2
    (elixir) lib/enum.ex:3161: Enumerable.List.reduce/3
    (elixir) lib/stream.ex:1433: Enumerable.Stream.do_each/4
    (elixir) lib/enum.ex:1823: Enum.map/2

Upvotes: 2

Views: 4036

Answers (2)

developer_hatch
developer_hatch

Reputation: 16224

You can use zip from Enum, like:

resultado=for {point, res} <- Enum.zip(points, results) do
  point ++ [res]
  end

Upvotes: 0

Dogbert
Dogbert

Reputation: 222118

Whenever you want to iterate over two enumerables simultaneously, you should think about using Enum.zip/2. This is how I'd do it with Enum.zip/2 and for:

for {point, result} <- Enum.zip(points, results) do
  point ++ [result]
end
|> IO.inspect

Output:

[[1.0, 2.0, 1.0], [5.0, 3.0, 3.0], [2.0, 4.0, 2.0], [3.0, 1.0, 1.0],
 [2.0, 2.0, 3.0], [4.0, 3.0, 2.0], [1.0, 2.0, 1.0], [2.0, 5.0, 3.0],
 [14.0, 13.0, 2.0], [11.0, 12.0, 1.0], [12.0, 15.0, 3.0], [32.0, 25.0, 2.0]]

Re: why your code doesn't work: Enum.into's second argument should be an enumerable. You probably want to wrap it in a list:

Enum.into(x, [Enum.fetch!(results, i)])

I'd suggest using the Enum.zip/2 solution though.

Upvotes: 9

Related Questions