def invert(map) when is_map(map) do
for {k, v} <- map, into: %{}, do: {v, k}
end
My Elixir program is synchronizing Robot Framework source code files with TestRail. Robot Framework defines automated test cases. TestRail is a web-based Test Case Management system. The goal is to synchronize TestRail to contain all the tests that are defined in the Robot Framework files, and in the same directory structure.Originally the Elixir program was specified to only create test cases in TestRail. When you are creating a test case, the TestRail API requires you to specify the ID of the directory (aka "section") where the case is written. For this I use an Elixir Map to map paths to section IDs. When I want to create a file in directory "/path/to/test.robot", then I Lookup the section ID from my map & then call the "add_case" TestRail API function.That version of the program was a success. My boss was impressed and next asked for enhancements to the program. The new functionality being requested is to have existing TestRail Test Cases get updated with the latest test steps defined in Robot Framework. Part of that update is to verify that the path to the test case is the same in the Robot Framework source code and in the TestRail. In this case we first call the TestRail API to lookup a test case, at which point we know the section ID that it belongs to. But we need to translate that to a directory path and confirm that this path is the same location as where the test file exists in the Robot Framework source code.For updating, it makes sense to also be able to use an Elixir Map to map from the Section ID back to the Path -- the inverse of the original map.It is true that I could iterate through the original map until I found the section ID in the value section, and then return the map index. But that seems awfully inefficient when you consider that there are hundreds of test files and thousands of tests. So I decided an inverse map would provide faster lookup, at the cost of more memory being used. Also note that in my scenario both the indexes and the values are unique; it is a 1-to-1 mapping.
======================================================= I welcome VSRE emails. Learn more at http://vsre.info/ =======================================================
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/b2c7e58a-ad99-4458-a45e-9f7d5f7fce15%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAJr6D4T05yO6NOL9QzB757KsOAALYd_ZF8gzcWW%2BYB51LmuBOQ%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/745bf765-c4b8-494e-9ded-7d1a50c05c5e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Hi Andrea,
I think there are two questions:
First question: what are use cases?
Basically it is whenever the keys and values in a map have equal importance as being the reference. Inverting a map allows you use a value to look up a key.
The following are use cases for inverting a map, where it makes sense to do a lookup on the key & also to do a lookup on the value:
Phone Book. You may have a name and want to lookup the phone number, or vice versa. (idea taken from here)
Converting between languages. To map words/expressions between 2 languages.
Encrypting/decrypting data
Capital city & State. ("given this capital city, what is its state?", "given this state, what is its capital city?")
Sports team & school
Sports player name & player number
Countries & their final ranked position (i.e. in Soccer World Cup)
Finally, to recap the motivation in the original proposal: Converting between English titles and record IDs for talking to APIs. The same argument could be applied for talking to a database instead of an API.
For example, for a school application you many need to convert between classroom_number & classroom_ID , or student_name & student_ID
Here are examples from other programming languages showing that developers are commonly asking about this functionality.
Ruby:
Python:
https://stackoverflow.com/questions/483666/python-reverse-invert-a-mapping
https://stackoverflow.com/questions/44851342/reverse-a-dictionary-in-python
https://stackoverflow.com/questions/7304980/invert-keys-and-values-of-the-original-dictionary
Perl:
https://stackoverflow.com/questions/6128970/inverting-a-hashs-key-and-values-in-perl
https://stackoverflow.com/questions/11902558/how-do-i-invert-a-hash-with-complex-values
Java:
https://stackoverflow.com/questions/20412354/reverse-hashmap-keys-and-values-in-java
https://stackoverflow.com/questions/9783020/bidirectional-map
One reason to implement Map.invert() now is to avoid further people asking about it in the future. ;)
Second question: is the function too small to add to the library?
I now think the initial code I proposed is inadequate. The Map.new/2 solution is also inadequate. A Map library implementation would need to consider what happens when the map contains duplicate values.
I'm thinking we should offer 2 variants of the invert() method: Map.invert/1 and Map.invert!/1.
The Map.invert!/1 method would expect a 1-to-1 map, and raise an exception if the map contains non-unique values
(i.e. the following would raise an error:
Map.invert!(%{a: 1, b: 1})
In contrast, the Map.invert/1 method would allow for non-unique values. It would return a map where the values are a list of keys in the original map.
(i.e.
Map.invert(%{"banana" => "yellow", "strawberry" => "red", "cherry" => "red"})
would return
%{"yellow" => ["banana"], "red" => ["strawberry", "cherry"]}.
This idea is from solutions found in other languages (i.e. "Perl Cookbook", "Ruby Cookbook 2nd ed", or see here or here for Python). This way no data is lost through the inversion. Ideally, if possible, we can use a property-based test to validate that inverting the map 2 times will always returns the initial map.
What are your thoughts?
Thanks,
Justin
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/221eeeb8-cd9c-4625-99a3-158e451b15fd%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CACh1tgG%2BMRtSeMNSaGiaDHqQSVCWpV8DRL6iz3KMAusYXtkO%2Bw%40mail.gmail.com.