Unique keys in map - pattern matching

Suppose, we have a map, whose keys are records: #{person, name, id} and values are ages. We know that there is no person with the same id. Is itpossible to write pattern matching shown below?:

Age = maps:get( #person{ id = 57 }, People )

Moreover, I would like also to know the name of a person, whose ID is 57. How to do it? An approach shown below doesn’t work:

Age = maps:get( #person{ name = Name, id =  57}, People)

In order to lookup value from the map - you need an entire key.

Since id is unique - you can rebuild your map to have id as a key, not #person{} record.
We can use map comprehension for it:

People = #{
  #person{name = "Alice",id = 58} => 21,
  #person{name = "Bob",id = 57} => 20
},
IdBasedMap = #{ Id => {Name, Age} || #person{id = Id, name = Name} := Age  <- People}.

Now using maps:get you will get a {Name, Age} tuple:

> maps:get(57, IdBasedMap).
{"Bob",20}
3 Likes

Thanks for answer. I actually need a record to be a key, so your solution doesn’t work for me. I think it would be better just to traverse map’s keys in recursion manner and look there for pattern. I guess it would work.

What if you use ETS instead of map?

1> ets:new(people, [bag, named_table]). %% Just an example
people
2> ets:insert(people, {person, 58, "Alice", 21}).
true
3> ets:insert(people, {person, 57, "Bob", 20}).
true
4> ets:match(people, {person, 57, '$1', '$2'}).
[["Bob",20]]
5> ets:tab2list(people).
[{person,58,"Alice",21},{person,57,"Bob",20}]

I need a record and map, because that is what we are using now during the class, but thanks. It seems that I found a long, but proper way to do it :slight_smile: