Changeset v0.2.0 Changeset

The Changeset module allows for calculating the Levenshtein distance between two lists, or the actual edit steps required to go from one list to another.

Summary

Functions

Calculate the minimal steps (insertions, deletions, substitutions and moves) required to turn one given list into another given list

Calculate the minimal steps (insertions, deletions, substitutions and moves) required to turn one given list into another given list using a custom cost function, which takes an edit type (:insert, :delete or :substitute), a value and an index and returns a cost (i.e. an integer)

Calculate the Levenshtein distance between two lists, i.e. how many insertions, deletions or substitutions are required to turn one given list into another

Functions

edits(source, target)

Specs

edits([], []) :: [tuple]

Calculate the minimal steps (insertions, deletions, substitutions and moves) required to turn one given list into another given list.

Examples

iex> taylor_swift_songs = [22, 15, "I Knew You Were Trouble"]
[22, 15, "I Knew You Were Trouble"]
iex> positive_integers = [22, 7, 15, 186, 33]
[22, 7, 15, 186, 33]
iex> Changeset.edits(taylor_swift_songs, positive_integers)
[{:insert, 7, 1}, {:substitute, 186, 3}, {:insert, 33, 4}]
iex> Changeset.edits(positive_integers, taylor_swift_songs)
[{:delete, 7, 1}, {:substitute, "I Knew You Were Trouble", 2}, {:delete, 33, 4}]

It also supports moves, each of which is really only a deletion followed by an insertion.

iex> Changeset.edits(~w( a v e r y ), ~w( g a r v e y ))
[{:insert, "g", 0}, {:move, "r", 3, 2}]
edits(source, target, cost_func)

Specs

edits([], [], (atom, any, non_neg_integer -> number)) :: [tuple]

Calculate the minimal steps (insertions, deletions, substitutions and moves) required to turn one given list into another given list using a custom cost function, which takes an edit type (:insert, :delete or :substitute), a value and an index and returns a cost (i.e. an integer).

(Note that the cost function is applied before insertions and deletions are converted into moves, meaning it will never receive a :move edit as an argument.)

Examples

For instance, making substitutions more costly will result in the algorithm replacing them with insertions and deletions instead.

iex> Changeset.edits(~w( a b c ), ~w( a d c ))
[{:substitute, "d", 1}]
iex> Changeset.edits(~w( a b c ), ~w( a d c ), fn type, _value, _idx ->
...>   if type == :substitute, do: 3, else: 1
...> end)
[{:insert, "d", 1}, {:delete, "b", 1}]
levenshtein(source, target)

Specs

levenshtein([], []) :: non_neg_integer

Calculate the Levenshtein distance between two lists, i.e. how many insertions, deletions or substitutions are required to turn one given list into another.

Examples

iex> taylor_swift_songs = [22, 15, "I Knew You Were Trouble"]
[22, 15, "I Knew You Were Trouble"]
iex> positive_integers = [22, 7, 15, 186, 33]
[22, 7, 15, 186, 33]
iex> Changeset.levenshtein(taylor_swift_songs, positive_integers)
3