Packages

Structure-preserving filter/reject for nested maps and lists: drop or take keys and values at any depth without flattening or losing data. Zero runtime dependencies.

Current section

Files

Jump to
nested_filter lib nested_filter.ex
Raw

lib/nested_filter.ex

defmodule NestedFilter do
@moduledoc """
Documentation for NestedFilter.
"""
@doc """
Take a (nested) map and filter out any keys with specified values in the
filter_values list. Specify a list of empty values in options[:remove_empty]
that should be removed after filtering out specified values.
"""
@spec reject_keys_by_value(map :: map(), filter_values :: list()) :: map()
def reject_keys_by_value(map, filter_values) do
cond do
is_nested_map?(map) ->
new_map = map
|> Enum.reduce(%{}, fn({key, val}, acc) ->
Map.put(acc, key, reject_keys_by_value(val, filter_values)) end)
Map.drop(new_map, filterable_keys(new_map, filter_values))
is_map(map) ->
Map.drop(map, filterable_keys(map, filter_values))
true ->
map
end
end
defp filterable_keys(map, filter_values) when is_list(filter_values) do
map
|> Map.keys
|> Enum.filter(fn(key) -> Enum.member?(filter_values, map[key]) end)
end
defp filterable_keys(map, filter_values), do: map
defp is_nested_map?(map) do
cond do
is_map(map) ->
map
|> Enum.any?(fn{key, _} -> is_map(map[key]) end)
true ->
false
end
end
end