# morphix v0.3.0 Morphix

Morphix provides convenience methods for dealing with Maps, Lists, and Tuples.

`morphiflat/1` and `morphiflat!/1` flatten maps, discarding top level keys.

### Examples:

``````iex> Morphix.morphiflat %{flatten: %{this: "map"}, if: "you please"}
{:ok, %{this: "map", if: "you please"}}

iex> Morphix.morphiflat! %{flatten: %{this: "map"}, o: "k"}
%{this: "map", o: "k"}
``````

`morphify!/2` and `morphify/2` will take either a List or a Tuple as the first argument, and a function as the second. Returns a map, with the keys of the map being the function applied to each member of the input.

### Examples:

``````iex> Morphix.morphify!({[1,2,3], [12], [1,2,3,4]}, &length/1)
%{1 => [12], 3 => [1,2,3], 4 => [1,2,3,4]}
``````

`atomorphify/1` and `atomorphiform/1` take a map as an input and return the map with all string keys converted to atoms. `atomorphiform/1` is recursive. `atomorphiform/2` and `atomormiphify/2` take `:safe` as a second argument, they will not convert string keys if the resulting atom has not been defined.

### Examples:

``````iex> Morphix.atomorphify(%{"a" => "2", :a => 2, 'a'  => :two})
{:ok, %{:a => 2, 'a' => :two }}
``````

`compactify` and `compactiform` take a map as an input and return a filtered map, removing any keys with nil values or with an empty map as a value.

`partiphify!/2` and `partiphify/2` take a list `l` and an integer `k` and partition `l` into `k` sublists of balanced size. There will always be `k` lists, even if some must be empty.

### Examples:

``````iex> Morphix.partiphify!([:a, :b, :c, :d, :e, :f], 4)
[[:c], [:d], [:e, :a], [:f, :b]]

iex> Morphix.partiphify!([:a, :b, :c, :d, :e], 4)
[[:b], [:c], [:d], [:e, :a]]

iex> Morphix.partiphify!([:a, :b, :c, :d], 4)
[[:a], [:b], [:c], [:d]]

iex> Morphix.partiphify!([:a, :b, :c], 4)
[[:a], [:b], [:c], []]
``````

# Link to this section Summary

## Functions

Takes a map as an argument and returns `{:ok, map}`, with all string keys (including keys in nested maps) converted to atom keys

Takes a map and a list of allowed strings as arguments and returns `{:ok, map}`, with any strings that are in the list converted to atoms, and any strings that are not in the list left as strings

Takes a map as an argument and returns the same map, with all string keys (including keys in nested maps) converted to atom keys

Takes a map and a list of allowed strings as arguments and returns the same map, with any strings that are in the list converted to atoms, and any strings that are not in the list left as strings

Takes a map as an argument and returns `{:ok, map}`, with string keys converted to atom keys. Does not examine nested maps

Takes a map and a list of allowed strings to convert to atoms and returns `{:ok, map}`, with string keys in the list converted to atoms. Ignores nested maps

Takes a map as an argument and returns the same map with string keys converted to atom keys. Does not examine nested maps

Takes a map and a list of allowed strings to convert to atoms and returns the same map, with string keys in the list converted to atoms. Ignores nested maps

Removes keys with nil values from maps, handles nested maps and treats empty maps as nil values

Removes keys with nil values from nested maps, also eliminates empty maps

Takes a map and removes any keys that have nil values

Takes a map and removes keys that have nil values, or are empty maps

Takes a map and returns a flattened version of that map. If the map has nested maps (or the maps nested maps have nested maps, etc.) morphiflat moves all nested key/value pairs to the top level, discarding the original keys

Takes a map and returns a flattend version of that map, discarding any nested keys

Takes a List and a function as arguments and returns `{:ok, Map}`, with the keys of the map the result of applying the function to each item in the list

Takes a list and a function as arguments and returns a Map, with the keys of the map the result of applying the function to each item in the list

Divides a list into k distinct sub-lists, with partitions being as close to the same size as possible

Divides a list into k distinct sub-lists, with partitions being as close to the same size as possible

# Link to this section Functions

`atomorphiform(map()) :: {:ok, map()}`

Takes a map as an argument and returns `{:ok, map}`, with all string keys (including keys in nested maps) converted to atom keys.

### Examples:

``````iex> Morphix.atomorphiform(%{:this => %{map: %{"has" => "a", :nested => "string", :for =>  %{a: :key}}}, "the" =>  %{"other" => %{map: :does}}, as: "well"})
{:ok,%{this: %{map: %{has: "a", nested: "string", for: %{a: :key}}}, the: %{other: %{map: :does}}, as: "well"} }

iex> Morphix.atomorphiform(%{"this" => ["map", %{"has" => ["a", "list"]}], "inside" => "it"})
{:ok, %{this: ["map", %{has: ["a", "list"]}], inside: "it"}}
``````
Link to this function atomorphiform(map, allowed)
`atomorphiform(map(), :safe) :: {:ok, map()}`
`atomorphiform(map(), list()) :: {:ok, map()}`

Takes a map and a list of allowed strings as arguments and returns `{:ok, map}`, with any strings that are in the list converted to atoms, and any strings that are not in the list left as strings.

Works recursively on embedded maps.

### Examples:

``````iex> map = %{"memberof" => "atoms", "embed" => %{"will" => "convert", "thelist" => "to atoms"}}
iex> Morphix.atomorphiform(map, ["memberof", "thelist"])
{:ok, %{"embed" => %{"will" => "convert", thelist: "to atoms"}, memberof: "atoms"}}
``````
`atomorphiform!(map()) :: map()`

Takes a map as an argument and returns the same map, with all string keys (including keys in nested maps) converted to atom keys.

### Examples:

``````iex> Morphix.atomorphiform!(%{:this => %{map: %{"has" => "a", :nested => "string", :for =>  %{a: :key}}}, "the" =>  %{"other" => %{map: :does}}, as: "well"})
%{this: %{map: %{has: "a", nested: "string", for: %{a: :key}}}, the: %{other: %{map: :does}}, as: "well"}

iex> Morphix.atomorphiform!(%{"this" => ["map", %{"has" => ["a", "list"]}], "inside" => "it"})
%{this: ["map", %{has: ["a", "list"]}], inside: "it"}
``````
Link to this function atomorphiform!(map, allowed)
`atomorphiform!(map(), :safe) :: map()`
`atomorphiform!(map(), list()) :: map()`

Takes a map and a list of allowed strings as arguments and returns the same map, with any strings that are in the list converted to atoms, and any strings that are not in the list left as strings.

Works recursively on embedded maps.

### Examples:

``````iex> map = %{"memberof" => "atoms", "embed" => %{"will" => "convert", "thelist" => "to atoms"}}
iex> Morphix.atomorphiform!(map, ["memberof", "thelist"])
%{"embed" => %{"will" => "convert", thelist: "to atoms"}, memberof: "atoms"}
``````
``````iex> map = %{"id" => "fooobarrr", "date_of_birth" => ~D[2014-04-14]}
%{"date_of_birth" => ~D[2014-04-14], "id" => "fooobarrr"}
iex> Morphix.atomorphiform!(map)
%{id: "fooobarrr", date_of_birth: ~D[2014-04-14]}``````
`atomorphify(map()) :: {:ok, map()}`

Takes a map as an argument and returns `{:ok, map}`, with string keys converted to atom keys. Does not examine nested maps.

### Examples

``````iex> Morphix.atomorphify(%{"this" => "map", "has" => %{"string" => "keys"}})
{:ok, %{this: "map", has: %{"string" => "keys"}}}

iex> Morphix.atomorphify(%{1 => "2", "1" => 2, "one" => :two})
{:ok, %{1 => "2", "1": 2, one: :two}}
``````
Link to this function atomorphify(map, allowed)
`atomorphify(map(), :safe) :: {:ok, map()}`
`atomorphify(map(), list()) :: {:ok, map()}`

Takes a map and a list of allowed strings to convert to atoms and returns `{:ok, map}`, with string keys in the list converted to atoms. Ignores nested maps.

### Examples:

``````iex> Morphix.atomorphify(%{"allowed_key" => "exists", "non_existent_atom" => "does_not", 1 => "is_ignored"}, ["allowed_key"])
{:ok, %{ "non_existent_atom" => "does_not", 1 => "is_ignored", allowed_key: "exists"}}
``````
`atomorphify!(map()) :: map()`

Takes a map as an argument and returns the same map with string keys converted to atom keys. Does not examine nested maps.

### Examples

``````iex> Morphix.atomorphify!(%{"this" => "map", "has" => %{"string" => "keys"}})
%{this: "map", has: %{"string" => "keys"}}

iex> Morphix.atomorphify!(%{1 => "2", "1" => 2, "one" => :two})
%{1 => "2", "1": 2, one: :two}
``````
Link to this function atomorphify!(map, allowed)
`atomorphify!(map(), :safe) :: map()`
`atomorphify!(map(), list()) :: map()`

Takes a map and a list of allowed strings to convert to atoms and returns the same map, with string keys in the list converted to atoms. Ignores nested maps.

### Examples:

``````iex> Morphix.atomorphify!(%{"allowed_key" => "exists", "non_existent_atom" => "does_not", 1 => "is_ignored"}, ["allowed_key"])
%{"non_existent_atom" => "does_not", 1 => "is_ignored", allowed_key: "exists"}
``````
```compactiform(map()) ::
{:ok, map()} | {:error, %BadMapError{__exception__: term(), term: term()}}```

Removes keys with nil values from maps, handles nested maps and treats empty maps as nil values.

### Examples

``````iex> Morphix.compactiform(%{a: nil, b: "not", c: %{d: nil, e: %{}, f: %{g: "value"}}})
{:ok, %{b: "not", c: %{f: %{g: "value"}}}}

iex> Morphix.compactiform(5)
``````
`compactiform!(map()) :: map() | no_return()`

Removes keys with nil values from nested maps, also eliminates empty maps.

### Examples

``````iex> Morphix.compactiform!(%{nil_nil: nil, not_nil: "a value", nested: %{nil_val: nil, other: "other"}})
%{not_nil: "a value", nested: %{other: "other"}}

iex> Morphix.compactiform!(%{nil_nil: nil, not_nil: "a value", nested: %{nil_val: nil, other: "other", nested_empty: %{}}})
%{not_nil: "a value", nested: %{other: "other"}}
``````
`compactify(map()) :: {:ok, map()} | no_return()`

Takes a map and removes any keys that have nil values.

### Examples

``````iex> Morphix.compactify(%{nil_key: nil, not_nil: "real value"})
{:ok, %{not_nil: "real value"}}

iex> Morphix.compactify("won't work")
``````
`compactify!(map()) :: map() | no_return()`

Takes a map and removes keys that have nil values, or are empty maps.

### Examples

``````iex> Morphix.compactify!(%{nil_key: nil, not_nil: "nil"})
%{not_nil: "nil"}

iex> Morphix.compactify!(%{empty: %{}, not: "not"})
%{not: "not"}

iex> Morphix.compactify!({"not", "a map"})
** (BadMapError) expected a map, got: {"not", "a map"}
``````
`morphiflat(map()) :: {:ok | :error, map() | String}`

Takes a map and returns a flattened version of that map. If the map has nested maps (or the maps nested maps have nested maps, etc.) morphiflat moves all nested key/value pairs to the top level, discarding the original keys.

### Examples:

``````iex> Morphix.morphiflat %{this: %{nested: :map, inner: %{twonested: :map, is: "now flat"}}}
{:ok, %{nested: :map, twonested: :map, is: "now flat"}}
``````

In the example, the key `:this` is discarded, along with the key `inner`, because they both point to map values.

Will return `{:error, <input> is not a Map}` if the input is not a map.

### Examples:

``````iex> Morphix.morphiflat({1,2,3})
{:error, "{1, 2, 3} is not a Map"}
``````
`morphiflat!(map()) :: map()`

Takes a map and returns a flattend version of that map, discarding any nested keys.

### Examples:

``````iex> Morphix.morphiflat! %{you: "will", youwill: %{be: "discarded"}}
``````
Link to this function morphify(enum, funct)
`morphify([any()], (... -> any())) :: {:ok | :error, map() | String.t()}`
`morphify(tuple(), (... -> any())) :: {:ok | :error, map() | String.t()}`

Takes a List and a function as arguments and returns `{:ok, Map}`, with the keys of the map the result of applying the function to each item in the list.

If the function cannot be applied, will return `{:error, message}`

### Examples

``````iex> Morphix.morphify([[1,2,3], [12], [1,2,3,4]], &Enum.count/1)
{:ok, %{1 => [12], 3 => [1,2,3], 4 => [1,2,3,4]}}

iex> Morphix.morphify({[1,2,3], [12], [1,2,3,4]}, &length/1)
{:ok, %{1 => [12], 3 => [1,2,3], 4 => [1,2,3,4]}}

iex> Morphix.morphify([1,2], &String.length/1)
{:error, "Unable to apply &String.length/1 to each of [1, 2]"}
``````
Link to this function morphify!(enum, funct)
`morphify!([any()], (... -> any())) :: map()`
`morphify!(tuple(), (... -> any())) :: map()`

Takes a list and a function as arguments and returns a Map, with the keys of the map the result of applying the function to each item in the list.

### Examples

``````iex> Morphix.morphify!([[1,2,3], [12], [1,2,3,4]], &Enum.count/1)
%{1 => [12], 3 => [1,2,3], 4 => [1,2,3,4]}
``````
Link to this function partiphify(list, k)
```partiphify(list(), integer()) ::
{:ok, [list(list(), any())]} | {:error, term()}```

Divides a list into k distinct sub-lists, with partitions being as close to the same size as possible

### Examples

``````iex> Morphix.partiphify([1,2,3,4,5,6], 4)
{:ok, [[3], [4], [5, 1], [6, 2]]}

iex> Morphix.partiphify(("abcdefghijklmnop" |> String.split("", trim: true)), 4)
{:ok, [["a", "b", "c", "d"], ["e", "f", "g", "h"], ["i", "j", "k", "l"], ["m", "n", "o", "p"]]}``````
Link to this function partiphify!(list, k)
`partiphify!(list(), integer()) :: [list(list(), any())] | no_return()`

Divides a list into k distinct sub-lists, with partitions being as close to the same size as possible

### Examples

``````iex> Morphix.partiphify!([1,2,3,4,5,6], 4)
[[3], [4], [5, 1], [6, 2]]

iex> Morphix.partiphify!(("abcdefghijklmnop" |> String.split("", trim: true)), 4)
[["a", "b", "c", "d"], ["e", "f", "g", "h"], ["i", "j", "k", "l"], ["m", "n", "o", "p"]]
``````