Iterating through a list

I have a list say

x = ["23gh", "56kh", "97mh"]

I would like to pass each element to Val in each iteration.

Say, in iteration 1 -------- Val = "23gh"
            iteration 2 -------- Val = "56kh"
            iteration 3 -------- Val = "97mh"

With Enum.at I can pass a specific index but not a set of indices. Any idea how to do it or if there is any other alternative to do this.

x = ["23gh", "56kh", "97mh"]

for comprehension might help:

for val <- x, do: val

Enum.map implementation:

# Normal
Enum.map(x, fn val ->
    val 
end)
# Anonymous fn (Shorthand Syntax)
Enum.map(x, &(&1))

If you need to iterate with index, then Enum.with_index might be combined with the above ones.

The official documentation is here:
https://hexdocs.pm/elixir/master/Enum.html

2 Likes

Thank you, so this exactly what I am trying to do, I am trying to put these values in a query field

query_result = %{
"blog" => %{
"posts" => [%{
"val" => here comes the elements of x
}]

My output should look something like this

"blog" => %{
"posts" => [%{"val" => "23gh"}, {"val" => "56kh"}, {"val" => "97mh"}] }

It would be easier if the data model or query result returning function gives you the data as such.

If that’s not the case, it would take multifold approach to do what you’re asking:

One example way of doing it in a single line would be like this:

{oldVal, NewVal} = Kernel.get_and_update_in(query_result, ["blog", "posts"], &{&1, hd(&1) |> Enum.flat_map(fn({k, v}) -> Enum.map(v, fn x -> %{k => x} end) end)})

{[%{"val" => ["23gh", "56kh", "97mh"]}],
 %{
   "blog" => %{
     "posts" => [%{"val" => "23gh"}, %{"val" => "56kh"}, %{"val" => "97mh"}]
   }
 }}

Other sane way would be to extract the val list:

valMap = Kernel.get_in(query_result, ["blog", "posts"]) |> List.first()
valList = valMap |> Map.get("val")
changedValList = valList |> Enum.map(&(%{"val" => &1}))
result = query_result |> Kernel.put_in(["blog", "posts"], changedValList)

%{
  "blog" => %{
    "posts" => [%{"val" => "23gh"}, %{"val" => "56kh"}, %{"val" => "97mh"}]
  }
}

Both are not the most optimized ways, if it has to be done recursively, so it’s better to get the data sorted at the source level, if possible.

Maybe you can use Enum.zip/2 and then Enum.reduce/3 here???

As I have exactly pointed out, it would be a loop within a loop. Also, Enum.zip/2 requires equal number of elements in both list to have the same number of elements as result. Here the user has to construct the list, which would render another loop to construct it.

1 Like