Handle adding fields into map

I’m trying to display fields into a table which I pass in a list of Tx structs inside of pagination like the one below.

%Scrivener.Page{
  entries: [
    %Tx{
      acct_num: "1111222233331111",
      id: 11,
      inserted_at: ~U[2020-05-26 19:51:31Z],
      updated_at: ~U[2020-05-26 19:51:31Z]
      ....
    },

My approach to display these calculated field values in the table is to take the entries list, calculate the values using Enum.map, and then map.merge with the original. Like below:

    Enum.map(txs, fn tx ->
      order_completed_at = [redacted]
      order_count = [redacted]

      Map.merge(
        txs,
        %{
          order_completed_at: order_completed_at,
          order_count: order_count
        }
      )
    end)

What is a better approach?

Your code is confusing: you are iterating over a bigger txs map but merge stuff to it inside each and every iteration? Didn’t you mean Map.merge(tx, ...) in your code?

Regardless of that, what’s more performant at runtime is to use the map | merging operator:

%{old_map | order_completed_at: order_completed_at, order_count: order_count}

Do have in mind that this requires that the fields already exist in old_map or else you get a runtime error. You cannot use this construct to add new keys to a map.

Enum.map(txs, fn tx ->
  %{tx |
      order_completed_at: [redacted],
      order_count: [redacted]
  }
end)

?

or

Enum.map(txs, fn tx ->
  tx
  |> Map.put(order_completed_at, [redacted])
  |> Map.put(order_count, [redacted])
end)

?

Your first is definitely performing faster btw.

I didn’t know that, tnx :slight_smile:

I’m adding new information to the map.

In that case Map.merge will have to do. :slight_smile:

You likely have to calculate these new values per transaction so I see nothing wrong with your code.

1 Like

Your input looks like nested structs, not like regular maps. You should never add keys to a struct that aren’t already there.

2 Likes

You’re right, so if I needed to add information that’s being passed in to the form. How would I do that?

If you are retrieving those fields from the database I guess you could also use something like virtual fields and select_merge/3.

Either change the defstruct to allow for the additional fields and use already proposed map update syntax (%{ foo | bar: value } or if you can’t change the defstrucht use Map.from_struct and then use Map.merge/3 or Map.put/3 or Map.merge/2,3.

1 Like