confused with python dictionary methods.values() .keys() - python

why this code isn't working? trying to get returns on items which value==key
L=[0,2,2,1,5,5,6,10]
x=dict(enumerate(L))
y=(filter(x.keys()==x.values(), x.items()))
print(list(y))

The keys() method returns a view of all of the keys.
The values() method returns a view of all of the values.
So, x.keys()==x.values() is asking whether all of the keys equal all of the values, which is of course not true.
Also, filter wants a function. But you're not passing it a function, you're just passing it the result of x.keys()==x.values(), or False. To turn that into a function, you'd need to use def or lambda to create a new function.
The function you want to create is a function that takes an item, and returns true if the key equals the value. Since an item is just a 2-element tuple with the key and value for that item, the function to check that is:
y = filter((lambda item: item[0] == item[1]), x.items())
Or, if that's a bit too confusing, don't try to write it inline; just def it separately:
def key_equals_value(item):
key, value = item
return key == value
y = filter(key_equals_value, x.items())
However, this is pretty clumsy; it's much easier to write it as a comprehension than a filter call:
y = ((key, value) for (key, value) in x.items() if key == value)
As a general rule, whenever you don't already have a function to pass to filter or map, and would have to create one with def or lambda, a comprehension will usually be more readable, because you can just write the expression directly.
And, if you want a list rather than a generator, you can do that with a comprehension just by changing the parens to square brackets:
y = [(key, value) for (key, value) in x.items() if key == value]
And, if you want just the values, not the key-value pairs:
y = [value for (key, value) in x.items() if key == value]
If you find yourself confused by comprehensions, they can always be converted into nested statements, with an append at the bottom. So, that last one is equivalent to:
y = []
for key, value in x.items():
if key == value:
y.append(value)
Also, you don't really need a dict here in the first place; you just want to iterate over the index, value pairs. So:
y = [value for (index, value) in enumerate(L) if index == value]

Related

How to extract items within nested lists containing nested dictionaries in python [duplicate]

I haven't found is there a way to do this.
Let's say I recieve a JSON object like this:
{'1_data':{'4_data':[{'5_data':'hooray'}, {'3_data':'hooray2'}], '2_data':[]}}
It's hard to instantly say, how should I get value from 3_data key: data['1_data']['4_data'][1]['3_data']
I know about pprint, it helps to understand structure a bit.
But sometimes data is huge, and it takes time
Are there any methods that may help me with that?
Here are a family of recursive generators that can be used to search through an object composed of dicts and lists. find_key yields a tuple containing a list of the dictionary keys and list indices that lead to the key that you pass in; the tuple also contains the value associated with that key. Because it's a generator it will find all matching keys if the object contains multiple matching keys, if desired.
def find_key(obj, key):
if isinstance(obj, dict):
yield from iter_dict(obj, key, [])
elif isinstance(obj, list):
yield from iter_list(obj, key, [])
def iter_dict(d, key, indices):
for k, v in d.items():
if k == key:
yield indices + [k], v
if isinstance(v, dict):
yield from iter_dict(v, key, indices + [k])
elif isinstance(v, list):
yield from iter_list(v, key, indices + [k])
def iter_list(seq, key, indices):
for k, v in enumerate(seq):
if isinstance(v, dict):
yield from iter_dict(v, key, indices + [k])
elif isinstance(v, list):
yield from iter_list(v, key, indices + [k])
# test
data = {
'1_data': {
'4_data': [
{'5_data': 'hooray'},
{'3_data': 'hooray2'}
],
'2_data': []
}
}
for t in find_key(data, '3_data'):
print(t)
output
(['1_data', '4_data', 1, '3_data'], 'hooray2')
To get a single key list you can pass find_key to the next function. And if you want to use a key list to fetch the associated value you can use a simple for loop.
seq, val = next(find_key(data, '3_data'))
print('seq:', seq, 'val:', val)
obj = data
for k in seq:
obj = obj[k]
print('obj:', obj, obj == val)
output
seq: ['1_data', '4_data', 1, '3_data'] val: hooray2
obj: hooray2 True
If the key may be missing, then give next an appropriate default tuple. Eg:
seq, val = next(find_key(data, '6_data'), ([], None))
print('seq:', seq, 'val:', val)
if seq:
obj = data
for k in seq:
obj = obj[k]
print('obj:', obj, obj == val)
output
seq: [] val: None
Note that this code is for Python 3. To run it on Python 2 you need to replace all the yield from statements, eg replace
yield from iter_dict(obj, key, [])
with
for u in iter_dict(obj, key, []):
yield u
How it works
To understand how this code works you need to be familiar with recursion and with Python generators. You may also find this page helpful: Understanding Generators in Python; there are also various Python generators tutorials available online.
The Python object returned by json.load or json.loads is generally a dict, but it can also be a list. We pass that object to the find_key generator as the obj arg, along with the key string that we want to locate. find_key then calls either iter_dict or iter_list, as appropriate, passing them the object, the key, and an empty list indices, which is used to collect the dict keys and list indices that lead to the key we want.
iter_dict iterates over each (k, v) pair at the top level of its d dict arg. If k matches the key we're looking for then the current indices list is yielded with k appended to it, along with the associated value. Because iter_dict is recursive the yielded (indices list, value) pairs get passed up to the previous level of recursion, eventually making their way up to find_key and then to the code that called find_key. Note that this is the "base case" of our recursion: it's the part of the code that determines whether this recursion path leads to the key we want. If a recursion path never finds a key matching the key we're looking for then that recursion path won't add anything to indices and it will terminate without yielding anything.
If the current v is a dict, then we need to examine all the (key, value) pairs it contains. We do that by making a recursive call to iter_dict, passing that v is its starting object and the current indices list. If the current v is a list we instead call iter_list, passing it the same args.
iter_list works similarly to iter_dict except that a list doesn't have any keys, it only contains values, so we don't perform the k == key test, we just recurse into any dicts or lists that the original list contains.
The end result of this process is that when we iterate over find_key we get pairs of (indices, value) where each indices list is the sequence of dict keys and list indices that succesfully terminate in a dict item with our desired key, and value is the value associated with that particular key.
If you'd like to see some other examples of this code in use please see how to modify the key of a nested Json and How can I select deeply nested key:values from dictionary in python.
Also take look at my new, more streamlined show_indices function.

how to get the corresponding key for the maximum value in dictionary list in the most effecient way?

Let's assume that there is a dictionary list like this one:
lst = {(1,1):2, (1,2):5, (1,3):10, (1,4):14, (1,6):22}
I want a simple (the most efficient) function that returns the dictionary key which its value is the maximum.
For example:
key_for_max_value_in_dict(lst) = (1,6)
because the tuple (1,6) has the most value (22).
I came up with this code which might be the most efficient one:
max(lst, key=lambda x: lst[x])
Use a comprehension for that like:
Code:
max((v, k) for k, v in lst.items())[1]
How does it work?
Iterate over the items() in the dict, and emit them as tuples of (value, key) with the value first in the tuple. max() can then find the largest value, because tuples sort by each element in the tuple, with first element matching first element. Then take the second element ([1]) of the max tuple since it is the key value for the max value in the dict.
Test Code:
lst = {(1,1):2, (1,2):5, (1,3):10, (1,4):14, (1,6):22}
print(max((v, k) for k, v in lst.items())[1])
Results;
(1, 6)
Assuming you're using a regular unsorted dictionary, you'll need to walk down the entire thing once. Keep track of what the largest element is and update it if you see a larger one. If it is the same, add to the list.
largest_key = []
largest_value = 0
for key, value in lst.items():
if value > largest_value:
largest_value = value
largest_key = [key]
elif value == largest_value:
largest_key.append(key)

How to access dictionary elements in a list in python

I'm trying to understand about dictionaries and list in Python.
Assume that I have a list which contains 3 dictionaries
Ex. item_list = [price,stock,quantity]
price, stock and quantity are the dictionaries here. Each dictionary has few key-value pairs like
price = {'toys':25,'clothes':[12,15,20]}
I know to access individual elements, I can use a for loop with the keys specified like:
for item in item_list:
print item['toys']
How do I access the elements without directly mentioning the key in the for loop?
You can iterate over a dictionary just like you can iterate over a list.
for item in item_list:
for key in item:
print item[key]
In a sense, you're still mentioning the keys, but you're not referencing them explicitly by their value.
If you're just interested in the values you can use the values() method:
for item in item_list:
for key in item.values():
print item[key]
My preferred way to iterate over dictionaries though is with items, which returns a tuple of key, value pairs.
for item in item_list:
for key, value in item.items():
print key, value
I would do something like this:
for item in item_list:
for key, value in item.iteritems():
print key, value
Let us say, you have a list like this
prices_list = [{'toys':25,'clothes':[12,15,20]},{'toys':35,'clothes':[12,15,20]}]
And you would like to get the value corresponding to toys, but without specifying the name in the for loop. So, you can use operator.itemgetter like this
from operator import itemgetter
getter = itemgetter("toys")
print [getter(item) for item in prices_list]
# [25, 35]
The same can be used like this
total = 0
for item in prices_list:
total += getter(item)
for d in item_list:
for i in d.values():
print i
You could also call d.items() and get back tuples of (key, value) if you wanted access to both.
Additionally if you don't care about readability you could use this to get a list of all the values accross the dicts in your list.
[x for y in (i.values() for i in item_list) for x in y]
You can also use: [d for i in item_list for d in i.values()] to get the values and flatten them into a list (though yours would still be nested because of clothes' value being a list.
Finally you can merge the dictionaries into one if they have distinct keys:
joint_mapping = dict([d for i in item_list for d in i.items()])
or if they don't have unique values you can use the below code to produce a dict of lists of values. :
for k, v in [d for i in item_list for d in i.items()]:
new_d[k] = new_d.get(k, [])+[v]
You mentioned :
#Eenvincible - I would be inputting those values to other variable.
Print is just an example I gave. So would not want to hardcode the key.
I think you can do your trick using for loop as mentioned in other answers.
for item in item_list:
for key in item:
print item[key]
tempvariable = item[key]
.... do something here.
If you want to assign each value to a seperate variable, you should:
- First, assign that variables to any insignificant value EX: **None** or *""*
- Then, dynamically use the for loop to reassign each variable to new value using if condition or thier index.
EX:
price_toys , price_clothes , stock_toys , stock_clothes = None , None , None , None
for item in item_list:
for key in item:
tempvariable = item[key]
# condition to choose which varible will be set to the current value.
if item == "price" and key == "toys":
price_toys = tempvariable
# and so on

Python: Elements of dictionary

def big(dict, n):
line = []
for k in dict:
if k > n:
line.append(k)
return line
I have to find all the elements in dict larger than n.
However, my code only returns the largest number in dict larger than n.
What do I need to do in order to make it correct?
The return line is tabbed too far over, so it returns when the first key larger than n is found (Note: a dictionary isn't ordered by the way you write it), rather than going over all keys before returning. Try:
def big(dic, n):
line = []
for k in dic:
if k > n:
line.append(k)
return line
In fact, you might prefer it to use list comprehension (and the function becomes just one line).
def big(dic, n):
return [k for k in dic if k>n]
.
Dictionaries compomise of key value pairs, {key: value} and when we iterate over a dictionary we are iterating over it's keys. This explains the use of the variable k to iterate over the keys. That is,
[k for k in dic] = [key1, key2, ...]
Hence, if you want to find that with the largest value in the dictionary, you can use:
return [dic[k] for k in dic if dic[k]>n]
Note: I've changed the variable name to dic since (as #AndrewJaffe mentions) dict is a built-in object, and renaming it here may cause unexpected things to occur, and is generally considered bad practise. For example, if you wanted to check type(dic)==dict.
Naively iterating over a dictionary gives you a sequence of keys. not values.
So to do what you want, you need itervalues:
for k in d.itervalues(): ### call it "d" rather than "dict"
if k>n:
line.append(k)
Or, as others have pointed out, use a list comprehension.
Also, don't use dict for the name, as it shadows a builtin.
def big(dic, n):
line = []
for k in dic:
if dic[k]> n: #compare value instead of key
line.append(k) #use k if you're appending key else dic[k] for val
return line
output:
>>> print big({'a':10,'b':15, 'c':12},11)
['c']
move the return statement backwards two tabs otherwise it will return on the first value larger than n.

How to convert an associative array in python?

I am really new to python and I can't find any information about this. I have an associative array item,
item['id'] = 0
item['title'] = 'python'
I want to validate the contents of item but I dont want to use the index name like 'title' but just have a for loop and iterate over all entries in item regardless of their meaning. Something like that
for a in range(0, len(item)):
print (item[a])
Any ideas or suggestions?
In Python, associative arrays are called dictionaries.
A good way to iterate through a dict is to use .iteritems():
for key, value in item.iteritems():
print key, value
If you only need the values, use .itervalues():
for value in item.itervalues():
print value
As you learn more about Python and dictionaries, take note of the difference between .iteritems()/itervalues() (which returns an iterator) and items()/values()(which returns a list (array)).
In Python 3
.iteritems()/.itervalues() have been removed and items()/values()/keys() return iterators on the corresponding sequences.
for key, value in item.items():
print(key)
print(value)
There are three ways to iterate a dictionary:
item = {...}
for key in item: # alternatively item.iterkeys(), or item.keys() in python 3
print key, item[key]
item = {...}
for value in item.itervalues(): # or item.values() in python 3
print value
item = {...}
for key, value in item.iteritems(): # or item.items() in python 3
print key, value

Categories

Resources