Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stdlib] Implement Dict.popitem() method #2794

Closed
wants to merge 12 commits into from
Closed
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ what we publish.

### ⭐️ New

- `Dict` now supports `popitem`, which removes and returns the last item in the `Dict`.
The item is returned as a (key, value) pair.
([PR #2794](https://github.com/modularml/mojo/pull/2794)
by [@msaelices](https://github.com/msaelices)) and [@jayzhan211](https://github.com/jayzhan211)

- Add a `sort` function for list of `ComparableCollectionElement`s.
[PR #2609](https://github.com/modularml/mojo/pull/2609) by
[@mzaks](https://github.com/mzaks)
Expand Down
17 changes: 17 additions & 0 deletions stdlib/src/collections/dict.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,23 @@ struct Dict[K: KeyElement, V: CollectionElement](
return default.value()[]
raise "KeyError"

fn popitem(inout self) raises -> (K, V):
"""Remove and return an arbitrary key-value pair from the dictionary.

Returns:
A tuple containing the key and value of the removed item.

Raises:
"KeyError" if the dictionary is empty.
"""
if self.size == 0:
raise "KeyError: popitem(): dictionary is empty"
var reversed_items = reversed(self.items())
var entry_ref = reversed_items.__next__() # TODO: Use next() when supported in Mojo
var entry = entry_ref[]
_ = self.pop(entry.key)
return (entry.key, entry.value)

fn keys(
self: Reference[Self, _, _]
) -> _DictKeyIter[K, V, self.is_mutable, self.lifetime]:
Expand Down
27 changes: 27 additions & 0 deletions stdlib/test/collections/test_dict.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,32 @@ def test_pop_default():
assert_equal(-1, dict.pop("c", -1))


def test_popitem():
var dict = Dict[String, Int]()
dict["a"] = 1
dict["b"] = 2

var t1: (String, Int) = dict.popitem()
assert_equal(t1[0], "b")
assert_equal(t1[1], 2)
assert_equal(1, len(dict))

dict["c"] = 3

var t2: (String, Int) = dict.popitem()
assert_equal(t2[0], "c")
assert_equal(t2[1], 3)
assert_equal(1, len(dict))

var t3: (String, Int) = dict.popitem()
assert_equal(t3[0], "a")
assert_equal(t3[1], 1)
assert_equal(0, len(dict))

with assert_raises(contains="KeyError"):
_ = dict.popitem()


def test_key_error():
var dict = Dict[String, Int]()

Expand Down Expand Up @@ -434,6 +460,7 @@ def test_dict():
test["test_compact", test_compact]()
test["test_compact_with_elements", test_compact_with_elements]()
test["test_pop_default", test_pop_default]()
test["test_popitem", test_popitem]()
test["test_key_error", test_key_error]()
test["test_iter", test_iter]()
test["test_iter_keys", test_iter_keys]()
Expand Down
Loading