Skip to content

Commit 441c333

Browse files
author
José Valim
committed
Optimize HashDict.take and HashDict.split, update CHANGELOG
1 parent bf35649 commit 441c333

File tree

4 files changed

+28
-32
lines changed

4 files changed

+28
-32
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* [IEx] Support `ls` with colored output
77
* [Kernel] Add `Enum.at`, `Enum.fetch` and `Enum.fetch!`
88
* [Kernel] Add `String.to_integer` and `String.to_float`
9-
* [Kernel] Add `Dict.pop` and `Dict.fetch!`
9+
* [Kernel] Add `Dict.take`, `Dict.drop`, `Dict.split`, `Dict.pop` and `Dict.fetch!`
1010
* [Kernel] Many optimizations for code compilation
1111
* [Kernel] `in` can be used with right side expression outside guards
1212
* [Kernel] Add `Node.get_cookie/0` and `Node.set_cookie/2`

lib/elixir/lib/dict.ex

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,13 @@ defmodule Dict do
367367
end
368368

369369
@doc """
370-
371-
Returns a tuple of two dicts, where the first dict contains only
372-
entries from `dict` with keys in `keys`, and the second dict
370+
Returns a tuple of two dicts, where the first dict contains only
371+
entries from `dict` with keys in `keys`, and the second dict
373372
contains only entries from `dict` with keys not in `keys`
374-
373+
375374
Any non-member keys are ignored.
376375
377-
## Examples
376+
## Examples
378377
379378
iex> d = HashDict.new([a: 1, b: 2])
380379
...> { d1, d2 } = Dict.split(d, [:a, :c])
@@ -398,11 +397,10 @@ defmodule Dict do
398397
end
399398

400399
@doc """
401-
402400
Returns a new dict where the the given `keys` a removed from `dict`.
403401
Any non-member keys are ignored.
404402
405-
## Examples
403+
## Examples
406404
407405
iex> d = HashDict.new([a: 1, b: 2])
408406
...> d = Dict.drop(d, [:a, :c, :d])
@@ -421,11 +419,10 @@ defmodule Dict do
421419
end
422420

423421
@doc """
424-
425422
Returns a new dict where only the keys in `keys` from `dict` are
426423
included. Any non-member keys are ignored.
427424
428-
## Examples
425+
## Examples
429426
430427
iex> d = HashDict.new([a: 1, b: 2])
431428
...> d = Dict.take(d, [:a, :c, :d])
@@ -441,7 +438,7 @@ defmodule Dict do
441438
@spec take(t, keys) :: t
442439
def take(dict, keys) do
443440
target(dict).take(dict, keys)
444-
end
441+
end
445442

446443
@doc """
447444
Returns an empty dict of the same type as `dict`.

lib/elixir/lib/hash_dict.ex

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -292,32 +292,35 @@ defmodule HashDict do
292292
and another containing entries with key not in keys.
293293
Returns a 2-tuple of the new dicts.
294294
"""
295-
def split(dict, keys) when keys == [] do
296-
{ new(), dict }
295+
def split(dict, keys) do
296+
split(keys, new, dict)
297297
end
298298

299-
def split(dict, keys) do
300-
acc = { new(), new() }
301-
dict_fold dict, acc, fn({ k, v }, { take, drop }) ->
302-
if Enum.member?(keys, k) do
303-
{ put(take, k, v), drop }
304-
else
305-
{ take, put(drop, k, v) }
306-
end
299+
defp split([], including, excluding) do
300+
{ including, excluding }
301+
end
302+
303+
defp split([key|keys], including, excluding) do
304+
case dict_delete(excluding, key) do
305+
{ excluding, _, 0 } -> split(keys, including, excluding)
306+
{ excluding, value, _ } -> split(keys, put(including, key, value), excluding)
307307
end
308308
end
309309

310310
@doc """
311311
Returns a new dict with only the entries
312-
which key is in keys
312+
which key is in keys.
313313
"""
314-
def take(_, keys) when keys == [] do
315-
new()
314+
def take(dict, keys) do
315+
take(dict, keys, new)
316316
end
317317

318-
def take(dict, keys) do
319-
{ members, _ } = split(dict, keys)
320-
members
318+
defp take(_dict, [], acc), do: acc
319+
defp take(dict, [key|keys], acc) do
320+
case fetch(dict, key) do
321+
{ :ok, value } -> take(dict, keys, put(acc, key, value))
322+
:error -> take(dict, keys, acc)
323+
end
321324
end
322325

323326
@doc """

lib/elixir/lib/list_dict.ex

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,10 @@ defmodule ListDict do
146146
and another containing entries with key not in keys.
147147
Returns a 2-tuple of the new dicts.
148148
"""
149-
def split(dict, keys) when keys == [] do
150-
{ new(), dict }
151-
end
152-
153149
def split(dict, keys) do
154150
acc = { new(), new() }
155151
Enum.reduce dict, acc, fn({ k, v }, { take, drop }) ->
156-
if Enum.member?(keys, k) do
152+
if :lists.member(k, keys) do
157153
{ [{k,v}|take], drop }
158154
else
159155
{ take, [{k,v}|drop] }

0 commit comments

Comments
 (0)