@@ -214,24 +214,7 @@ defmodule Map do
214214
215215 """
216216 @ spec new ( Enumerable . t ( ) , ( term -> { key , value } ) ) :: map
217- def new ( enumerable , transform )
218- def new ( % _ { } = enumerable , transform ) , do: new_from_enum ( enumerable , transform )
219- def new ( % { } = map , transform ) , do: new_from_map ( map , transform )
220- def new ( enumerable , transform ) , do: new_from_enum ( enumerable , transform )
221-
222- defp new_from_map ( map , transform ) when is_function ( transform , 1 ) do
223- iter = :maps . iterator ( map )
224- next = :maps . next ( iter )
225- :maps . from_list ( do_map ( next , transform ) )
226- end
227-
228- defp do_map ( :none , _fun ) , do: [ ]
229-
230- defp do_map ( { key , value , iter } , transform ) do
231- [ transform . ( { key , value } ) | do_map ( :maps . next ( iter ) , transform ) ]
232- end
233-
234- defp new_from_enum ( enumerable , transform ) when is_function ( transform , 1 ) do
217+ def new ( enumerable , transform ) when is_function ( transform , 1 ) do
235218 enumerable
236219 |> Enum . map ( transform )
237220 |> :maps . from_list ( )
@@ -989,16 +972,73 @@ defmodule Map do
989972 map_size ( map )
990973 end
991974
992- @ doc false
993- @ deprecated "Use Enum.filter/2 instead"
994- def filter ( map , fun ) when is_map ( map ) do
995- Enum . filter ( map , fun ) |> :maps . from_list ( )
975+ @ doc """
976+ Returns a map containing only those pairs from `map`
977+ for which `fun` returns a truthy value.
978+
979+ `fun` receives the key and value of each of the
980+ elements in the map as a key-value pair.
981+
982+ See also `reject/2` which discards all elements where the
983+ function returns a truthy value.
984+
985+ > Note: if you find yourself doing multiple calls to `Map.filter/2`
986+ > and `Map.reject/2` in a pipeline, it is likely more efficient
987+ > to use `Enum.map/2` and `Enum.filter/2` instead and convert to
988+ > a map at the end using `Map.new/1`.
989+
990+ ## Examples
991+
992+ iex> Map.filter(%{one: 1, two: 2, three: 3}, fn {_key, val} -> rem(val, 2) == 1 end)
993+ %{one: 1, three: 3}
994+
995+ """
996+ @ doc since: "1.13.0"
997+ @ spec filter ( map , ( { key , value } -> as_boolean ( term ) ) ) :: map
998+ def filter ( map , fun ) when is_map ( map ) and is_function ( fun , 1 ) do
999+ iter = :maps . iterator ( map )
1000+ next = :maps . next ( iter )
1001+ :maps . from_list ( do_filter ( next , fun ) )
9961002 end
9971003
998- @ doc false
999- @ deprecated "Use Enum.reject/2 instead"
1000- def reject ( map , fun ) when is_map ( map ) do
1001- Enum . reject ( map , fun ) |> :maps . from_list ( )
1004+ defp do_filter ( :none , _fun ) , do: [ ]
1005+
1006+ defp do_filter ( { key , value , iter } , fun ) do
1007+ if fun . ( { key , value } ) do
1008+ [ { key , value } | do_filter ( :maps . next ( iter ) , fun ) ]
1009+ else
1010+ do_filter ( :maps . next ( iter ) , fun )
1011+ end
1012+ end
1013+
1014+ @ doc """
1015+ Returns map excluding the pairs from `map` for which `fun` returns
1016+ a truthy value.
1017+
1018+ See also `filter/2`.
1019+
1020+ ## Examples
1021+
1022+ iex> Map.reject(%{one: 1, two: 2, three: 3}, fn {_key, val} -> rem(val, 2) == 1 end)
1023+ %{two: 2}
1024+
1025+ """
1026+ @ doc since: "1.13.0"
1027+ @ spec reject ( map , ( { key , value } -> as_boolean ( term ) ) ) :: map
1028+ def reject ( map , fun ) when is_map ( map ) and is_function ( fun , 1 ) do
1029+ iter = :maps . iterator ( map )
1030+ next = :maps . next ( iter )
1031+ :maps . from_list ( do_reject ( next , fun ) )
1032+ end
1033+
1034+ defp do_reject ( :none , _fun ) , do: [ ]
1035+
1036+ defp do_reject ( { key , value , iter } , fun ) do
1037+ if fun . ( { key , value } ) do
1038+ do_reject ( :maps . next ( iter ) , fun )
1039+ else
1040+ [ { key , value } | do_reject ( :maps . next ( iter ) , fun ) ]
1041+ end
10021042 end
10031043
10041044 @ doc false
0 commit comments