Dusty

Dusty

Passing an updated struct to each iteration of Enum

I am trying to iterate over a map, and repeatedly update a struct using each {k, v} pair in the map. But I am having difficulty figuring out how to pass the new/updated struct to the next iteration of the function. So I have something like:

struct = %MyStruct{...}
map = %{key1: value1, key2: value2,...}

def my_func(struct, key, value) do
  struct = # some code that updates the struct using the key and value
  struct # return the new struct
end

and I am trying to do something like:


struct = Enum.each(map, fn {key, value} -> my_func(struct, key, value) end)
{:ok, struct}

Obviously that code does not work, because Enum.each/2 returns :ok, but doesn’t carry the updated struct into the next iteration of the function, and doesn’t return the struct itself. It seems like I need a form of Enum.reduce/3 where the struct acts as the accumulator. How would you approach this?

Most Liked

henrik

henrik

Hi Dusty!

You could indeed use Enum.reduce/3:

iex> fake_struct = %{x: 0}
%{x: 0}
iex> map = %{key1: 1, key2: 2}
%{key1: 1, key2: 2}
iex> Enum.reduce(map, fake_struct, fn ({_k, v}, s) -> %{s | x: s.x + v} end)
%{x: 3}
Dusty

Dusty

@henrik @jmurphyweb

Thank you both for your time. It appears I just need a broader mental definition of an accumulator. Examples of reduce that I’ve seen always seem to use simple structures (like integer values) as an accumulator, but if the struct itself can be the accumulator then I think I’m in good shape.

jmurphyweb

jmurphyweb

Usually you would reduce over the map, and use a struct as the accumulator.

Enum.reduce(map, struct, fn {key, val}, new_struct -> 
  # ... perform some logic
  %{new_struct | key: value}
end)
jmurphyweb

jmurphyweb

@Dusty as a general rule, if you are trying to transform one enumerable into another and there is not a direct mapping (where Enum.map would be useful), then it can be done with Enum.reduce.

Often the shape/type of what you want to return will be passed in as the accumulator.

There’s a nice practice exercise that you can try, which is to ‘recreate’ Enum.map, Enum.filter etc using Enum.reduce (which I think is more or less how most Enum functions are built if you check the Elixir source code on Github).

Oliver

Oliver

Hi, Dusty.

Maps make useful accumulators for Enum.reduce/3, especially if you are interested in doing something for some of the items, or if the previously worked on items are needed in some form.

Another application is passing the whole state of my OTP process into the reduce so it can be used when modifying the enum or reading from it and even be updated while doing so, allowing state-sensitive functions to work on an enumerable. It depends what information you need to use and retain.

def handle_info({:message_with_list, list}, state) do
  state = Enum.reduce(list, state, &function_that_uses_state_and_list/2)
  {:noreply, state}
end

def handle_info({:more_complex, list}, state) do
  {state, modifed_list} = Enum.reduce(list, state, &function_that_uses_state_and_list/2)
  [...]
  {:noreply, state}
end

Etc.

Where Next?

Popular in Questions Top

lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
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
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics 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
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
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
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
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
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
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

We're in Beta

About us Mission Statement