View Source KeyDiff (KeyDiff v0.1.0)

Provides a single function, diff/3 for comparing two maps.

Lists

List diff is not implemented, and lists are treated like any single value of a key. If any key value is a list and the list contents change, then this is reflected in the updates list of the return tuple as a path to the key. The contents of the items in the list are not diffed.

In order to work around this limitation, it is advised to turn lists into mapped representations - especially where the items in the list are maps that can be uniquely identified by one of their keys.

For example:

a = %{"key_a" => [%{"id": 1}, %{"id": 2}, %{"id": 3}]}

should first be transformed into the following map:

a = %{"key_a" => %{1 => %{"id": 1}, 2 => %{"id": 2}, 3 => %{"id": 3}}}

This way, a can now be used with diff/3 and it will look for changes in the maps under the "key_a" key value.

Summary

Functions

Compares two maps/structs and returns a tuple of lists containing differences between the two maps.

Types

@type key() :: term()
@type key_path() :: key() | [key_path()]

Functions

@spec diff(a :: map(), b :: map(), options :: keyword()) ::
  {additions :: [key_path()], deletions :: [key_path()],
   updates :: [key_path()]}

Compares two maps/structs and returns a tuple of lists containing differences between the two maps.

The returning result is a tuple containing 3 lists:

list of additions - a list of keys new in the map list of deletions - a list of keys removed from the previous map list of updates - list of keys that had their values modified

Options

  • depth (default: nil), an integer that will stop the diffing at the specified level of depth in the map; it will recurse into the map only depth number of times. If not set or nil then it will process the entire map tree.

This is useful in quickly determining changes in depth number of levels, instead of having the entire structure processed.

Examples

# No differences between the two maps
iex> KeyDiff.diff(%{a: 1}, %{a: 1})
{[], [], []}

# Top-level key is changed.
iex> KeyDiff.diff(%{a: 1}, %{a: 2})
{[], [], [:a]}

# Top level key `:a` is removed and key `:b` is added
iex> KeyDiff.diff(%{a: 1}, %{b: 2})
{[:b], [:a], []}

# Second level key `:b` is removed and second level key `:c` is modified
# `[:a, [:b]]` represents the top-level key `:a` under which keys `[:b]` are removed
# from.
# `[:a, [:c]]` represent the top-level key `:a` under which keys `[:c]` are changed.
iex> KeyDiff.diff(%{a: %{b: "b", c: "c"}}, %{a: %{c: "d"}})
{[], [[:a, [:b]]], [[:a, [:c]]]}