Anshul-13J

Anshul-13J

Itertating a 2D matrix

Hey everyone, I am new to Elixir language and I am having some issues while writing a piece of code.

What I am given is a 2D array like

list1 = [
           [1 ,2,3,4,"nil"],
           [6,7,8,9,10,],
           [11,"nil",13,"nil",15],
           [16,17,"nil",19,20] ]

Now, what I’ve to do is to get all the elements that have values between 10 and 20, so what I’m doing is:


final_list = []
Enum.each(list1, fn row ->   
Enum.each(row, &(if (&1 >= 10 and &1 <= 99) do final_list = final_list ++ &1 end)) 
end
)

Doing this, I’m expecting that I’ll get my list of numbers in final_list but I’m getting blank final list with a warning like:

warning: variable "final_list" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)
  iex:5

:ok

and upon printing final_list, it is not updated.

When I try to check whether my code is working properly or not, using IO.puts as:

iex(5)> Enum.each(list1, fn row ->                                              ...(5)> Enum.each(row, &(if (&1 >= 10 and &1 <= 99) do IO.puts(final_list ++ &1) end))     
...(5)> end
...(5)> )

The Output is:

10


11
13
15
16
17
19
20
:ok

What could I possibly be doing wrong here? Shouldn’t it add the elements to the final_list?
If this is wrong ( probably it is), what should be the possible solution to this?

Any kind of help will be appreciated.

Most Liked

dpreston

dpreston

From your initial question I think you are missing a key difference between Python and Elixir. Elixir variables are immutable and you cannot modify them like you would in Python.

results = [] # <= create empty array
for x in range(1, 100):
  if 10 <= x <= 20:
    results.append(x) # <= append to the `results` array which is outside the `for` loop
  else:
   # skip x

# results = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

incorrectly translated to Elixir (similar to your initial attempt)

results = [] # <= create an empty array
Enum.each(1..100, fn x ->
  if x >= 10 and x <= 20, do: results = results ++ [x] # <= does NOT append to the `results` list
end)

# warning: variable "results" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)

instead should be written

results = Enum.reduce(1..100, [], fn x, acc -> # <= assign the final value of the accumulator to results
  if x >= 10 and x <= 20 do
    acc ++ [x] # <= append x to the accumulator
  else
    acc # <= do not modify the accumulator
  end
end)

# results = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

The difference is that Enum.reduce builds up the accumulator array and then assigns it all to results at the end, it doesn’t modify results as it processes each element of the list.
In fact, it cannot modify results even if we wanted to.

The full solution then looks like this,

list1 = [
  [1, 2, 3, 4, "nil"],
  [6, 7, 8, 9, 10],
  [11, "nil", 13, "nil", 15],
  [16, 17, "nil", 19, 20]
]
final_list = Enum.reduce(list1, [], fn inner_list, acc ->
  acc ++ Enum.reduce(inner_list, [], fn x, acc2 ->
    if x >= 10 and x <= 20 do
      acc2 ++ [x]
    else
      acc2
    end
  end)
end)

# => [10, 11, 13, 15, 16, 17, 19, 20]

If you don’t need to retain the nested structure or process the elements further, I would suggest a different approach. First flatten the inner lists and then filter with a simple boolean test.

final_list = list1 
|> List.flatten()
|> Enum.filter(&(&1 >=10 and &1 <= 20))

# final_list = [10, 11, 13, 15, 16, 17, 19, 20]
dimitarvp

dimitarvp

Banging your head against the wall is a slow way to learn, dude. Trust me I know, I’ve done the same way too many times.

You have to assign the result of almost every function to a variable in Elixir because it does NOT change a variable in place like in Python in many others; it returns a modified copy of the variable.

list = []
Enum.each([1,2,3], fn x ->
  list = list ++ (x*2)
end)

List is still [] in the end because the internal expression list = list ++ (x*2) is staying there and not going anywhere.

If you run the above you’ll get this message:

warning: variable "list" is unused (there is a variable with the same name in the context, use the pin operator (^) to match on it or prefix this variable with underscore if it is not meant to be used)

It’s telling you that you are throwing away list from inside the Enum.each block.

The way you would achieve the desired result is this:

list = Enum.map([1,2,3], fn x ->
  x * 2
end)

This goes through each element of the list, modifies it, and appends it to a resulting list.

TL;DR forget about using Enum.each or for to modify variables. They are not used for that, only for side effects (like printing to terminal, writing to files or external network services etc.)

arcyfelix

arcyfelix

In your specific example, it is better to use Enum.reduce.

Where Next?

Popular in Questions Top

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
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&amp;query=perfume&amp;page=2, I would like to get: ...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
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 I...
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
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New

Other popular topics Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
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
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
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
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127089 1222
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement