How to get results from a loop

I’m trying to get the batch Ids from a struct and save them in a map with out redundant batch ids. But I keep getting a blank map. My code is below

def get_card_batch_ids() do
    Ecards.all()
    |> case do
         nil -> %{Message: "Cards not foundt", Status: "1"}
         cards ->
           last_card_value = "fsdffd"
           map = Map.new()

           Enum.each(cards, fn card ->
             IO.inspect card.batchId

             if card.batchId == last_card_value do
               last_card_value = card.batchId
             else
               last_card_value = card.batchId
               map = Map.put(map, :BatchId, card.batchId)

               IO.inspect map
             end
           end)
           map
       end
end

Hi there.

Welcome to the forums.

To solve your specific problem you might want to use the Enum.uniq_by/2 function

Enum.uniq_by(cards, & &1.batchId) # Remove duplicates
|> Enum.map(& %{BatchId: &1.batchId}) # Mapping into a new map with an capitalised key

In general you cannot return anything from Enum.each. You need to use Enum.map/2 for that.

Also you should move away from thinking that you can update variables outside of functions. You can’t and you therefor need to look into functional patterns like map & reduce to transform data. Please ask if you have any additional questions.

2 Likes

Thank you alot. It worked

1 Like

What does the & &1. mean in the Remove duplicates line?

& &1 is a shorthand for writing fn(a) -> a end.

You can read more about functions here: https://elixirschool.com/en/lessons/basics/functions/

1 Like

Here is an introductory article on the different forms of Elixir’s capture syntax.

1 Like

As others have already said, & &1 is shorthand for fn a -> a end.

A function that returns its single argument, as is.

Both are a bit obfuscated though, and some prefer to use &Function.identity/1 in their code for readability.

1 Like

How can I select specific fields from a struct eg, name and age then add them to a map

Something like this?

struct = %MyStruct{a: 1, b: 2, c: 3, d: 4}
Map.take(struct, [:b, :d]) 

> %{b: 2, d: 4}
1 Like