Last active
December 21, 2019 12:14
-
-
Save boydm/ab7aec16d54709862ec3491c2b01ddda to your computer and use it in GitHub Desktop.
Elixir meyers_difference for Maps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Boydm.Utilities.Map do | |
#============================================================================ | |
# similar to List.meyers_difference, the below code compares two maps | |
# and generates a list of actions that can be applied to the first map | |
# to transform it into the second map. | |
#-------------------------------------------------------- | |
def difference(map_1, map_2) when is_map(map_1) and is_map(map_2) do | |
# remove any keys from map_1 that are simply not present (at all) in map_2 | |
difference = Enum.reduce(map_1, [], fn({k,_}, d)-> | |
case Map.has_key?(map_2, k) do | |
false -> [{:del, k} | d] | |
true -> d | |
end | |
end) | |
# add any puts for keys that have changed between map_2 to map_1 | |
Enum.reduce(map_2, difference, fn({k,v}, d)-> | |
case Map.has_key?(map_1, k) && (Map.get(map_1, k) == v) do | |
false -> [{:put, k, v} | d] | |
true -> d | |
end | |
end) | |
end | |
#-------------------------------------------------------- | |
def apply_difference(map, difference) when is_map(map) and is_list(difference) do | |
Enum.reduce(difference, map, fn(diff, acc)-> | |
case diff do | |
{:put, k, v} -> Map.put(acc, k, v) | |
{:del, k} -> Map.delete(acc, k) | |
end | |
end) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is another (non-golfed) version that lets you invert the diffs by keeping track of the initial values. This way you can apply the diff either way like such: