Navigating nested dictionary - python

I'm trying to wrap my head around how to navigate a series of dictionaries nested in a list.
For example: mydict = {'first':[{'second':2, 'third':3}, {'fourth':4}]}
When I type mydict.get('first'), I get the whole list.
I can't use indexing to get each individual dictionaries in the list (i.e. mydict.get(['first'][0] returns the whole list, and mydict.get(['first'][1]) returns an IndexError).
mydict.get(['first'][0]['second']) andmydict.get(['first']['second']) return TypeErrors.
So, if I wanted to call 'second' or 'fourth' or assign their values to variables, how would I do it?

For second:
mydict['first'][0]['second]
['first'] returns the array
[0] returns the first object of the array
['second'] gets the 'second' object
Perhaps try reshaping your data to something more convenient?

In your example, mydict isn't a series of dictionaries nested in a list. It is a dictionary that contains lists that, in turn, contain dictionaries.
So assuming you don't know which inner dictionary will contain the key you're looking for, you'd have to iterate over all the entries in the parent dictionary to find it. Something like:
desiredKey = 'second'
for listOfDict in mydict.values():
for childDict in listOfDict:
if desiredKey in childDict:
print(childDict[desiredKey])
This will only work if the key you're looking for is always in the inner most dictionaries.

Related

How to compare the values from a dictionary and list through iteration

I am trying to compare the value of each key from a dictionary to each value within a list. Unfortunately, I cannot figure out a way to do that, since in the second for loop, the variable "column" is a string key, and I want to iterate through both the same number of instances in my "row" list as there is columns. Lists can only take integers, and I don't think dictionaries can take integers to iterate. How can I write this, to be able to iterate through both the dictionary and list to compare.
The size of the list is the same as the size of the dictionary, in terms of instances within them.
for row in data:
for column in dna:
if dna[column] != int(row['?????']):
break
else:
print(row[0])
break
else:
print("No match")
The builtin function zip can be used to iterate in parallel over multiple iterables. You can achieve the desired result using it as follows:
for dict_key, list_item in zip(my_dict, my_list):
# your code here
In order to get acces to the keys and values, you should use:
for key, value in your_dictionary.items():
#your code here
when you use your_dictionary.items() what you got is access to an iterable that looks like dict_items([(key1,value1), (key2, value2), ...])

How to add elements of a list to existing dictionary based on key?

I have an iterator for creating multiple lists. I need to keep adding the generated list to a dictionary dict1 based on the key value k:
some value here = k
for a in jsoncontent:
list1.append(a["Value"])
dict1.setdefault(k, []).append(list1)
Right now I get:
{k:[[10,11],[12,32,6],[7,4]]}
But I need:
{k:[10,11,12,32,6,7,4]}
How do I merge these lists?
It sounds like you want extend versus append. extend inserts the contents of the list at the end of the list, while append insets its argument, a list in this case. See https://docs.python.org/3/library/stdtypes.html#mutable-sequence-types

Adding two asynchronous lists, into a dictionary

I've always found Dictionaries to be an odd thing in python. I know it is just me i'm sure but I cant work out how to take two lists and add them to the dict. If both lists were mapable it wouldn't be a problem something like dictionary = dict(zip(list1, list2)) would suffice. However, during each run the list1 will always have one item and the list2 could have multiple items or single item that I'd like as values.
How could I approach adding the key and potentially multiple values to it?
After some deliberation, Kasramvd's second option seems to work well for this scenario:
dictionary.setdefault(list1[0], []).append(list2)
Based on your comment all you need is assigning the second list as a value to only item of first list.
d = {}
d[list1[0]] = list2
And if you want to preserve the values for duplicate keys you can use dict.setdefault() in order to create value of list of list for duplicate keys.
d = {}
d.setdefault(list1[0], []).append(list2)

Accessing class variables from within a list without using for loop?

I have a list of class objects who have two values, x and y. This is my current code to grab an individual object from the list:
for object in object_list:
if object.x == 10 and object.y == 10:
current_object = object
break
And then I can do operations on the object by referencing current_object. However, my problem is that the list contains 2000 class object entries, and I worry that it will be very inefficient to iterate through the list like that until I find the desired object.
Is there a more efficient way for me to get my requested object?
If you are going to do the lookup again and again, then you can turn your list to a dictionary, like this
lookup = {(obj.x, obj.y): object for obj in object_list}
This will create a dictionary with keys as the tuples of x and y values from objects.
Now, you can simply do the lookup like this
lookup[(x_value, y_value)]
or if you want to return a default value if the key is not found in the dictionary, then you can use the dictionary.get, like this
lookup.get((x_value, y_value), None)
This will not throw a KeyError, if the key is not found in the dictionary, but return None.
Is there a more efficient way for me to get my requested object?
The above suggested dictionary method will be very fast, because the dictionary lookup can happen in constant time (as they internally use hash tables), but searching the list will be in linear time complexity (we need to iterate the list and check elements one by one).

List Comprehension of Lists Nested in Dictionaries

I have a dictionary where each value is a list, like so:
dictA = {1:['a','b','c'],2:['d','e']}
Unfortunately, I cannot change this structure to get around my problem
I want to gather all of the entries of the lists into one single list, as follows:
['a','b','c','d','e']
Additionally, I want to do this only once within an if-block. Since I only want to do it once, I do not want to store it to an intermediate variable, so naturally, a list comprehension is the way to go. But how? My first guess,
[dictA[key] for key in dictA.keys()]
yields,
[['a','b','c'],['d','e']]
which does not work because
'a' in [['a','b','c'],['d','e']]
yields False. Everything else I've tried has used some sort of illegal syntax.
How might I perform such a comprehension?
Loop over the returned list too (looping directly over a dictionary gives you keys as well):
[value for key in dictA for value in dictA[key]]
or more directly using dictA.itervalues():
[value for lst in dictA.itervalues() for value in lst]
List comprehensions let you nest loops; read the above loops as if they are nested in the same order:
for lst in dictA.itervalues():
for value in lst:
# append value to the output list
Or use itertools.chain.from_iterable():
from itertools import chain
list(chain.from_iterable(dictA.itervalues()))
The latter takes a sequence of sequences and lets you loop over them as if they were one big list. dictA.itervalues() gives you a sequence of lists, and chain() puts them together for list() to iterate over and build one big list out of them.
If all you are doing is testing for membership among all the values, then what you really want is to a simple way to loop over all the values, and testing your value against each until you find a match. The any() function together with a suitable generator expression does just that:
any('a' in lst for lst in dictA.itervalues())
This will return True as soon as any value in dictA has 'a' listed, and stop looping over .itervalues() early.
If you're actually checking for membership (your a in... example), you could rewrite it as:
if any('a' in val for val in dictA.itervalues()):
# do something
This saves having to flatten the list if that's not actually required.
In this particular case, you can just use a nested comprehension:
[value for key in dictA.keys() for value in dictA[key]]
But in general, if you've already figured out how to turn something into a nested list, you can flatten any nested iterable with chain.from_iterable:
itertools.chain.from_iterable(dictA[key] for key in dictA.keys())
This returns an iterator, not a list; if you need a list, just do it explicitly:
list(itertools.chain.from_iterable(dictA[key] for key in dictA.keys()))
As a side note, for key in dictA.keys() does the same thing as for key in dictA, except that in older versions of Python, it will waste time and memory making an extra list of the keys. As the documentation says, iter on a dict is the same as iterkeys.
So, in all of the versions above, it's better to just use in dictA instead.
In simple code just for understanding this might be helpful
ListA=[]
dictA = {1:['a','b','c'],2:['d','e']}
for keys in dictA:
for values in dictA[keys]:
ListA.append(values)
You can do some like ..
output_list = []
[ output_list.extend(x) for x in {1:['a','b','c'],2:['d','e']}.values()]
output_list will be ['a', 'b', 'c', 'd', 'e']

Categories