Reputation: 157
If I do something like this
some_obj = {"a": 1, "b": 2, "c": 3}
first, *rest = some_obj
I'll get a list, but I want it in 2 dictionaries: first = {"a": 1}
and rest = {"b": 2, "c": 3}
. As I understand, I can make a function, but I wonder if I can make it in one line, like in javascript with spread operator.
Upvotes: 5
Views: 1396
Reputation: 3591
k = next(iter(some_obj)) # get the first key
first = {k: some_obj.pop(k)}
rest = some_obj
If you need to keep the original object intact - note this degrades from O(1) to O(n) in both time and space:
k = next(iter(some_obj))
rest = some_obj.copy()
first = {k: rest.pop(k)}
Upvotes: 3
Reputation: 10229
A oneliner inspired by Abdul Niyas P M's:
first, rest = dict([next(i := iter(some_obj.items()))]), dict(i)
Uses an assignment expression, introduced in Python 3.8 almost two years ago.
Upvotes: 3
Reputation: 106618
@AbdulNiyasPM's answer is perfectly fine, but since you asked for a one-liner, here's one way to do it (though you would have to do from operator import itemgetter
first):
first, rest = map(dict, itemgetter(slice(0, 1), slice(1, None))(list(some_obj.items())))
If you prefer not to import anything, you can use a similar one-liner with a lambda
function that takes one fixed argument and the rest as variable-length arguments:
first, rest = map(dict, (lambda f, *r: ((f,), r))(*some_obj.items()))
Demo: https://replit.com/@blhsing/ImpeccableEllipticalGeeklog
Upvotes: 1
Reputation: 24602
I don't know if there is a reliable way to achieve this in one line, But here is one method.
First unpack the key
s and values
(.items()
). Using some_obj
only iterate through the keys.
>>> some_obj = {"a":1, "b":2, "c": 3} >>> first, *rest = some_obj.items()
But this will return a tuple,
>>> first
('a', 1)
>>> rest
[('b', 2), ('c', 3)]
But you can again convert back to dict with just a dict
call.
>>> dict([first])
{'a': 1}
>>> dict(rest)
{'b': 2, 'c': 3}
Upvotes: 8