Access an Arbitrary Element in a Dictionary in Python

Access an arbitrary element in a dictionary in Python

On Python 3, non-destructively and iteratively:

next(iter(mydict.values()))

On Python 2, non-destructively and iteratively:

mydict.itervalues().next()

If you want it to work in both Python 2 and 3, you can use the six package:

six.next(six.itervalues(mydict))

though at this point it is quite cryptic and I'd rather prefer your code.

If you want to remove any item, do:

key, value = mydict.popitem()

Note that "first" may not be an appropriate term here because dict is not an ordered type in Python < 3.6. Python 3.6+ dicts are ordered.

Pythonic way to access arbitrary element from dictionary

Similar to your second solution, but slightly more obvious, in my opinion:

return next(iter(dictionary.values()))

This works in python 2 as well as in python 3, but in python 2 it's more efficient to do it like this:

return next(dictionary.itervalues())

How to efficiently get an arbitrary item from a dict?

Pop item returns an arbitrary item in O(1), which you can then put back into the dict (also O(1)).

key, val = D.popitem()
D[key] = val

Since Python 3.7 LIFO order is guaranteed for dict.popitem, so you don't have to worry about it messing up ordering either.

This is significantly faster than creating an item iterator just to get the first item:

>>> timeit k,v = D.popitem(); D[k] = v
107 ns ± 0.0716 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
>>> timeit next(iter(D.items()))
164 ns ± 0.0687 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Note that next(iter(ordered_dict)) is O(1) but next(iter(std_dict)) can be O(n) in worst-case.

What is the fastest way to get an arbitrary element out of a Python dictionary?

There are multiple ways, but you'll need to make some tradeoffs. One way is to empty the dictionary out using popitem; it is atomic, and will use an arbitrary order. But it modifies the dictionary itself; whatever item was selected isn't in it anymore. The next method that comes to mind is iterating as usual, even while modifying the dictionary; the order of items might change, so you could get items any number of times. To track that, you could build a second set of visible keys. It's reasonably cheap to add keys to the set, cheap to check if each item is in it, and when you've gone through the whole dictionary you can check if the set matches the dictionary's keys to determine if there are ones you missed (or removed). You do end up building a key set but only one item per iteration; in the pessimal case we have the dictionary being modified in such a way we scan through the whole set of visited items before finding the new item.

Is there a reason this data needs to be kept in a dictionary only? For instance, if we consider a system where we're shuffling songs, we might not want to visit the whole library but only place a limit on how recently a song has been played. That could be more efficiently handled using a list of songs wherein we can read a random index, a set of recently played songs to avoid duplicates, and a queue (perhaps in a list or deque) of songs allowing us to update the set in order (removing the last entry each iteration). Bear in mind that references are reasonably cheap.

Rethinking one more step we wouldn't need the keys to check for duplicates if they simply aren't in our candidates; by just swapping the oldest played song with the randomly selected next song, both the played and candidate lists stay constant size and no lookups are needed since songs are in only one of the lists.

Another idea is to use collections.ChainMap to keep a consistent view into two dictionaries; ones that have been visited and ones that have not. You could then migrate items from the latter to the former by way of popitem, ensuring a readable method of processing everything in the collection while keeping it dictionary-like.

def getnewitem(chainmap):
# Raises KeyError when finished
key,value=chainmap.maps[0].popitem()
chainmap.maps[1][key]=value
return key,value

As that means both dictionaries keep changing, it's likely not the fastest overall, but it maintains both a dictionarylike collection and a capability to process all items. It does lose the ability to directly delete items, since ChainMap cannot hide inherited mappings; you'd need to remove them from the backing dictionaries.

Iterate through items of an arbitrary layered dictionary in Python

This is best solved using recursion:

def iter_leafs(d):
for key, val in d.items():
if isinstance(val, dict):
yield from iter_leafs(val)
else:
yield val

Example usage:

>>> d = {'a':{'a':{'y':2}},'b':{'c':{'a':5}},'x':{'a':{'m':6}}}
>>> list(iter_leafs(d))
[6, 5, 2]

If you also want to keep track of the keys:

def iter_leafs(d, keys=[]):
for key, val in d.items():
if isinstance(val, dict):
yield from iter_leafs(val, keys + [key])
else:
yield keys + [key], val

>>> list(iter_leafs(d))
[(['x', 'a', 'm'], 6), (['b', 'c', 'a'], 5), (['a', 'a', 'y'], 2)]

How to access the first and the last elements in a dictionary?

Use an OrderedDict, because a normal dictionary doesn't preserve the insertion order of its elements when traversing it. Here's how:

# import the right class
from collections import OrderedDict

# create and fill the dictionary
d = OrderedDict()
d['first'] = 1
d['second'] = 2
d['third'] = 3

# retrieve key/value pairs
els = list(d.items()) # explicitly convert to a list, in case it's Python 3.x

# get first inserted element
els[0]
=> ('first', 1)

# get last inserted element
els[-1]
=> ('third', 3)

Access nested dictionary items via a list of keys?

Use reduce() to traverse the dictionary:

from functools import reduce  # forward compatibility for Python 3
import operator

def getFromDict(dataDict, mapList):
return reduce(operator.getitem, mapList, dataDict)

and reuse getFromDict to find the location to store the value for setInDict():

def setInDict(dataDict, mapList, value):
getFromDict(dataDict, mapList[:-1])[mapList[-1]] = value

All but the last element in mapList is needed to find the 'parent' dictionary to add the value to, then use the last element to set the value to the right key.

Demo:

>>> getFromDict(dataDict, ["a", "r"])
1
>>> getFromDict(dataDict, ["b", "v", "y"])
2
>>> setInDict(dataDict, ["b", "v", "w"], 4)
>>> import pprint
>>> pprint.pprint(dataDict)
{'a': {'r': 1, 's': 2, 't': 3},
'b': {'u': 1, 'v': {'w': 4, 'x': 1, 'y': 2, 'z': 3}, 'w': 3}}

Note that the Python PEP8 style guide prescribes snake_case names for functions. The above works equally well for lists or a mix of dictionaries and lists, so the names should really be get_by_path() and set_by_path():

from functools import reduce  # forward compatibility for Python 3
import operator

def get_by_path(root, items):
"""Access a nested object in root by item sequence."""
return reduce(operator.getitem, items, root)

def set_by_path(root, items, value):
"""Set a value in a nested object in root by item sequence."""
get_by_path(root, items[:-1])[items[-1]] = value

And for completion's sake, a function to delete a key:

def del_by_path(root, items):
"""Delete a key-value in a nested object in root by item sequence."""
del get_by_path(root, items[:-1])[items[-1]]


Related Topics



Leave a reply



Submit