-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new lists:mapkeyfind/3 function to map finding #4831
Conversation
Stdlib's lists module has some functions for searching a list for a tuple whose given element position compares equal to a given value, but it lacks the same functionality for maps, i.e., a function for searching a list for a map whose given key compares equal to the given value. This new function allow us to find such a map in a list without the need to create a fun to filter it every time a map search is required. Usage: 1> lists:mapkeyfind(42, id, [#{id => 1, person => jane}, #{id => 42, answer => 42}]). #{id => 42, answer => 42} 2> lists:mapkeyfind(not_found, id, [#{id => 1, person => jane}, #{id => 42, answer => 42}]). false 3> lists:mapkeyfind(not_found, id, []). false
A while after maps were added there was a pretty long discussion on the erlang-questions mailing list about adding this function, together with all the other variants of mapfind(Key, Value, ListOfMaps) ->
lists:search(fun(M) -> try maps:get(Key, M) == Value catch _:_ -> false end, ListOfMaps). or something similar. This quite a lot more verbose than what you are proposing, so I personally do not have a problem with adding functions to handle lists of maps. For me the largest and hardest question for this is naming it correctly as we have multiple options:
We also should consider how this fits into the greater scheme of things, such as #2952 or a more general lens library for erlang. This was just my way of saying that although the addition of this function is simple, it may take some thinking to know that this is the solution that we want. |
Hi, @garazdawi, I can understand your point. I agree we can use About your question on naming scheme, I believe we should keep it in the same
I've started learning Erlang two years ago, so I'm not completely aware of this discussion. Does someone proposed it again recently or this discussion occurred only that time? Should we discuss it again or I should close this pull request as duplicated? Thank you very much. |
+1 |
May I suggest another alternative (4?):
This function would returns the first element that is a superset of the map given as parameter. I haven't given much thought to the exact function naming or in which module should such a function reside, I just think that a match based interface would probably be more appropriate for a list of maps. Any thoughts? |
In my current opinion adding tuple support to the lists module was a mistake and that it should instead have been a separate module such as
It has been discussed multiple times in different forums, though I don't think anyone yet has submitted a PR.
You can leave it open and I'll schedule a meeting of the OTP technical board to see what opinion we have about this. |
Being so records-oriented it would make sense to have made a new module called In my own little version of this here https://gitlab.com/zxq9/lom/-/blob/master/src/lom.erl there has arisen the need in one project that uses it to provide a second set of functions that permits a key to not exist at all (so maps:get/2 would raise an exception, which is too strict for that case). This can't happen with records, of course, because you either have the element or it isn't defined as the same type of record, but in sparse JSON data this can come up and needs to be handled. I'm thinking about expanding the return type from Anyway, my point in mentioning this is there are a few weird little corners with this based on the difference between records and maps, and how you decide to deal with them can mean doubling the number of functions added to the module if it were to be included in |
If we anticipate more functions in the list of maps family, a new module would be preferable IMHO. (Craig's lib has 10 functions, but you can imagine filter, partition and more.) I suggest the name Regarding @asabil's |
@zuiderkwast I meant it exactly as you describe it: Fruits = [
#{fruit => banana, color => yellow},
#{fruit => banana, angle => 45, color => yellow},
#{fruit => {apple}, color => red}
].
mapfind(#{fruit => banana, angle => 45}, Fruits).
{ok, #{fruit => banana, angle => 45, color => yellow}}
mapfind(#{fruit => banana}, Fruits).
{ok, #{fruit => banana, color => yellow}}
mapfind(#{fruit => apple, color=> red}, Fruits).
error It is basically a generalisation of |
Hello! We have just completed our OTP technical board meeting. We want to have this type of functionality in stdlib, but we do not want to have it in the Instead what we would like to see is a new module similar (or identical) to the In the long run, we do intend to start looking at something like functional lenses which could also be used for this type of functionality, but that far away so adding this module first is a step in the right direction. |
Stdlib's lists module has some functions for searching a list for a
tuple whose given element position compares equal to a given value, but
it lacks the same functionality for maps, i.e., a function for searching
a list for a map whose given key compares equal to the given value.
This new function allow us to find such a map in a list without the need
to create a fun to filter it every time a map search is required.
Usage: