hauks96

hauks96

Building map from list of columns and list of values

I’m trying to implement an efficient generic function to map the results from a Postgrex call into a map. Any suggestions?

  • Example result from postgrex:
%Postgrex.Result{
   columns: ["first_column", "second_column"],
   command: :select,
   num_rows: 4,
   rows: [["a", 1], ["b", 2], ["c", 3], ["d", 4]]
 }
  • Desired output
[
%{first_column: "a", second_column: 1},
%{first_column, "b", second_column: 2},
%{first_column, "c", second_column: 3},
%{first_column, "d", second_column: 4}
]

Marked As Solved

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

No worries about being a noob, but as a general note for future questions it’s also best to show the code that you’ve tried so that we can help you learn.

The most succinct way to do this is with Enum.zip. Assuming you have the struct you listed as a result variable you can do:

Enum.map(result.rows, fn row ->
  result.columns
  |> Enum.zip(row)
  |> Map.new()
end)

Also Liked

Sebb

Sebb

I can only second that. To cleanse yourself from the sins of the imperative world you should reimplement the Enum functions. This is one of the exercises in the Exercism Elixir Track. This is very much recommended! Reimplmenting Enum is not easy, so there are a lot of very good execises to lead you there.

Sebb

Sebb

You do not need to index the lists. They already fit together.

iex(1)> Enum.zip(["first_column", "second_column"], ["a", 1])
[{"first_column", "a"}, {"second_column", 1}]
benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

I’d highly recommend starting with a simpler question and seeing if you can build it from scratch without Enum, it’ll help with those for i cobwebs. Given:

columns = ["first_column", "second_column"]
values = ["a", 1]

How would you build a function that returned:

[{["first_column", "a"}, {"second_column", 1}]

without using Enum or List or anything like that? (Hint, recursion!)

Sebb

Sebb

What have you tried?

Eiji

Eiji

Here are 2 examples:

defmodule Example do
  def sample1(%Postgrex.Result{columns: columns, rows: rows}) do
    Enum.map(rows, fn row ->
      Enum.zip_reduce(columns, row, %{}, &Map.put(&3, String.to_atom(&1), &2))
    end)
  end

  def sample2(%Postgrex.Result{columns: _columns, rows: []}), do: []

  def sample2(%Postgrex.Result{columns: columns, rows: [row | rows]}) do
    [sample2(columns, row, %{}) | sample2(%Postgrex.Result{columns: columns, rows: rows})]
  end

  defp sample2([], [], acc), do: acc

  defp sample2([column | columns], [value | row], acc) do
    acc = Map.put(acc, String.to_atom(column), value)
    sample2(columns, row, acc)
  end
end

The first example is really short as it uses a helper Enum functions. On the other hand the second example uses just a simple pattern-matching.

Helpful resources:

  1. Enum.map/2
  2. Enum.zip_reduce/4
  3. Map.put/3
  4. String.to_atom/3
  5. Kernel.SpecialForms.&/1 (Capture operator)
  6. Patterns and Guards

Please keep in mind below every time you want to convert String to Atom:

Warning: this function creates atoms dynamically and atoms are not garbage-collected. Therefore, string should not be an untrusted value, such as input received from a socket or during a web request. Consider using to_existing_atom/1 instead.

Source: String.to_atom/3 — Elixir documentation

Where Next?

Popular in Questions Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement