How do I do this with Python list? (itemgetter?) - python

[{'id':44}, {'name':'alexa'},{'color':'blue'}]
I want to select whatever in the list that is "id".
Basically, I want to print 44, since that's "id" in the list.

That's a weird data structure... A list of one item dictionaries.
key = 'id'
l = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
print [ x[key] for x in l if key in x ][0]
Assuming you can rely on key being present precisely once...
Maybe you should just convert the list into a dictionary first:
key = 'id'
l = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
d = {}
for x in l:
d.update(x)
print d[key]

All the other answers solve your problem, I am just suggesting an alternative way of going about doing this.
Instead of having a list of dicts where you query on the key and have to iterate over all list items to get values, just use a dict of lists. Each key would map to a list of values (or just one value if all your dicts had distinct sets of keys).
So,
data=[{'id':44}, {'name':'alexa'},{'color':'blue'}]
becomes
data={'id':[44], 'name':['alexa'], 'color':['blue']}
and you can neatly access the value for 'id' using data['id'] (or data['id'][0] if you only need one value).
If all your keys are distinct across the dicts (as in your example) you don't even have to have lists of values.
data={'id':44, 'name':'alexa', 'color':'blue'}
Not only does this make your code cleaner, it also speeds up your queries which no longer have to iterate over a list.

Probably this is the best solution:
>>> L = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
>>> newd = {}
>>> for d in L:
... newd.update(d)
>>> newd['id']
44

You could do something like this:
>>> KEY = 'id'
>>>
>>> my_list = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
>>> my_ids = [x[KEY] for x in my_list if KEY in x]
>>> print my_ids
[44]
Which is obviously a list of the values you want. You can then print them as required.

>>> from itertools import dropwhile
>>> def find_value(l, key):
... return dropwhile(lambda x: key not in x, l).next()[key]
>>> find_value([{'id':44}, {'name':'alexa'},{'color':'blue'}], "id")
This will do a linear search, but only until the element is found.
If you want to have proper error handling, use:
def find_value(l, key):
try:
return dropwhile(lambda x: key not in x, l).next()[key]
except StopIteration:
raise ValueError(key)

>>> L = [{'id':44}, {'name':'alexa'},{'color':'blue'}]
>>> newd=dict(d.items()[0] for d in L)
>>> newd['id']
44

Related

How to access key by value in a dictionary?

I have a dict that looks like the following:
d = {"employee": ['PER', 'ORG']}
I have a list of tags ('PER', 'ORG',....) that is extracted from the specific entity list.
for t in entities_with_tag: # it includes words with a tag such as: [PER(['Bill']), ORG(['Microsoft']),
f = t.tag # this extract only tag like: {'PER, ORG'}
s =str(f)
q.add(s)
Now I want if {'PER, ORG'} in q, and it matched with d.values(), it should give me the keys of {'PER, ORG'} which is 'employee'. I try it this but does not work.
for x in q:
if str(x) in str(d.values()):
print(d.keys()) # this print all the keys of dict.
If I understand correctly you should loop he dictionary instead of the tag list. You can check if the dictionary tags are in the list using sets.
d = {"employee": ['PER', 'ORG'],
"located": ["ORG", "LOC"]}
q = ["PER", "ORG", "DOG", "CAT"]
qset = set(q)
for key, value in d.items():
if set(value).issubset(qset):
print (key)
Output:
employee
You mean with... nothing?
for x in q:
if str(x) in d.values():
print(d.keys())
What you can do is to switch keys and values in the dict and then access by key.
tags = ('PER', 'ORG')
data = dict((val, key) for key, val in d.items())
print(data[tags])
Just be careful to convert the lists in tuples, since lists are not hashable.
Another solution would be to extract both key and value in a loop. But that's absolutely NOT efficient at all.
for x in q:
if str(x) in str(d.values()):
for key, val in d.items():
if val == x:
print(key) # this print all the keys of dict.
What you can do is make two lists. One which contains the keys and one which contains the values. Then for the index of the required value in the list with values you can call the key from the list of keys.
d = {"employee": ['PER', 'ORG']}
key_list = list(d.keys())
val_list = list(d.values())
print(key_list[val_list.index(['PER','ORG'])
Refer: https://www.geeksforgeeks.org/python-get-key-from-value-in-dictionary/

Pythonic way of updating value in dictionary

I have this current code
lst = [1,2,3,4]
c = dict((el,0) for el in lst)
for key in lst:
c[key] += increase_val(key)
Is there a more pythonic way to do it? Like using map? This code words but i would like probably a one-liner or maybe better way of writing this
In my opinion, that is a very clean, readable way of updating the dictionary in the way you wanted.
However, if you are looking for a one-liner, here's one:
new_dict = {x: y + increase_val(x) for x, y in old_dict.items()}
What's different is that this create's a new dictionary instead of updating the original one. If you want to mutate the dictionary in place, I think the plain old for-loop would be the most readable alternative.
In your case no need of c = dict((el,0) for el in lst) statement, because we create dictionary where value of each key is 0.
and in next for loop you are adding increment value to 0 i.e. 0 + 100 = 100, so need of addition also.
You can write code like:
lst = [1,2,3,4]
c = {}
for key in lst:
c[key] = increase_val(key)
collection.Counter()
Use collections.Counter() to remove one iteration over list to create dictionary because default value of every key in your case is 0.
Use Collections library, import collections
Demo:
>>> lst = [1,2,3,4]
>>> data = collections.Counter()
>>> for key in lst:
data[key] += increase_val(key)
collection.defaultdict()
We can use collections.defaultdict also. Just use data = collections.defaultdict(int) in above code. Here default value is zero.
But if we want to set default value to any constant value like 100 then we can use lambda function to set default value to 100
Demo:
>>> data = {}
>>> data["any"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'any'
Get key error because there is on any key in dictionary.
>>> data1 = collections.defaultdict(lambda:0, data)
>>> data1["any"]
0
>>> data1 = collections.defaultdict(lambda:100, data)
>>> data1["any"]
>>> 100

Python a list and a dictionary

I have a list (x) and a dictionary (d)
x=[1,3,5]
d={1:a,2:b,3:c,4:d,5:e}
As you can see a few variables match a few keys in the dictionary
But how can I print only the values whose key matches a variable in the list?
I tried a for loop but it returns only the key. Thanks for any assistance!
Something like this?
for key in d:
if key in x:
print d[key]
This will loop through every key in the dictionary, and if the key appears in x then it will print the value of x.
try like this:
>>> x=[1,3,5]
>>> d={1:'a',2:'b',3:'c',4:'d',5:'e'}
>>> for key in d.keys():
... if key in x:
... print d[key]
...
a
c
e
or you can use dict.get:
>>> for num in x:
... print d.get(num,"not found")
...
a
c
e
dict.get will give the value of key, if key is found in dictionary else defaultvalue
syntax : dict.get(key[, default])
If you are sure that all of the keys in x are in your dictionary
for key in x:
print(d[key])
Otherwise you can check first
for key in x:
if x in d:
print(d[key])
You can use this one-liner list comprehension:
[d[key] for key in x if key in d]
This will also work if not all items in the list are keys in the dictionary.
for example:
>>> d = {1:'a', 3:'b'}
>>> x = [1, 2]
>>> [d[key] for key in x if key in d]
... ['a']

Iterating over dict values

If i would like to iterate over dictionary values that are stored in a tuple.
i need to return the object that hold the "CI" value, i assume that i will need some kind of a for loop :
z = {'x':(123,SE,2,1),'z':(124,CI,1,1)}
for i, k in db.z:
for k in db.z[i]:
if k == 'CI':
return db.z[k]
i am probably missing something here, a point of reference would be good.
if there is a faster way doing so it would all so help greatly
Ways to iterate over a dictionary
First things first, there are a few ways you can loop over a dictionary.
Looping directly over the dictionary:
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> for key in z:
... print key,
...
'x' 'z'
Notice that the loop variables that get returned when you just loop over a dictionary are the keys, not the values associated with those keys.
Looping over the values of a dictionary:
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> for value in z.values(): # Alternatively itervalues() for memory-efficiency (but ugly)
... print value,
...
(123,'SE',2,1) (124,'CI',1,1)
Looping over both the keys and the values:
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> for key, value in z.items(): # Again, iteritems() for memory-efficiency
... print key, value,
...
'x' (123,'SE',2,1) 'z' (124,'CI',1,1)
The latter two are somewhat more efficient than looping over keys and running z[key] to obtain the value. It's also arguably more readable.
Building on these...
List Comprehensions
List comprehensions are great.
For the simple case of searching for just 'CI':
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> [key for key, value in z.items() if 'CI' in value]
['z']
For finding dict keys that hold several search items:
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> search_items = ('CI', 1) # Only keys that hold both CI and 1 will match
>>> [key for key, value in z.items() if all(item in value for item in search_items)]
['z']
For finding dict keys that hold any of multiple search items:
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> search_items = ('CI', 'SE', 'JP') # Keys that hold any of the three items will match
>>> [key for key, value in z.items() if any(item in value for item in search_items)]
['x', 'z']
If the latter two look a bit too complex as one-liners, you can re-write the last bit as a separate function.
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> search_items = ('CI', 'SE', 'JP') # Keys that hold any of the three items will match
>>> def match_any(dict_value, search_items):
... return any(item in dict_value for item in search_items)
...
>>> [key for key, value in z.items() if match_any(value, search_items)]
['x', 'z']
Once you get used to the [x for x in iterable if condition(x)] syntax, the format should be very easy to read and follow.
z = {'x':(123,"SE",2,1),'q':(124,"CI",1,1)}
for i in z.keys(): #reaching the keys of dict
for x in z[i]: #reaching every element in tuples
if x=="CI": #if match found..
print ("{} holding {}.".format(i,x)) #printing it..
This might solve your problem.
Output:
>>>
q holding CI.
>>>
Edit for your comment:
def func(*args):
mylist=[]
z = {'x':(123,"SE",2,1),'q':(124,"CI",1,1)}
for x,y in z.items():
for t in args:
if t in y:
mylist.append(x)
return mylist
print (func(1,"CI"))
Output:
>>>
['q', 'q', 'x']
>>>
Hope this is what you want, otherwise first method is already printing all keys, example output:
if x==1 or x=="CI":
>>>
x holding 1.
q holding CI.
q holding 1.
q holding 1.
>>>
There's no need to retrieve the key if you're only interested in the values:
In Python 2.x:
z = {'x':(123,"SE",2,1),'q':(124,"CI",1,1)}
for value in z.itervalues():
if 'CI' in value:
return value
In Python 3.x:
z = {'x':(123,"SE",2,1),'q':(124,"CI",1,1)}
for value in z.values():
if 'CI' in value:
return value
try this:
>>> z = {'x':(123,'SE',2,1),'z':(124,'CI',1,1)}
>>> list(filter(lambda x:'CI' in z.get(x),z))
['z']
z = {'x':(123,"SE",2,1),'q':(124,"CI",1,1)}
for key, val in z.items():
if 'CI' in val:
return z[key]

access value of a python dict() without knowing the keys

I have a dictionary of a list of dictionaries. something like below:
x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
The length of the lists (values) is the same for all keys of dict x.
I want to get the length of any one value i.e. a list without having to go through the obvious method -> get the keys, use len(x[keys[0]]) to get the length.
my code for this as of now:
val = None
for key in x.keys():
val = x[key]
break
#break after the first iteration as the length of the lists is the same for any key
try:
what_i_Want = len(val)
except TypeError:
print 'val wasn't set'
i am not happy with this, can be made more 'pythonic' i believe.
This is most efficient way, since we don't create any intermediate lists.
print len(x[next(iter(x))]) # 2
Note: For this method to work, the dictionary should have atleast one key in it.
What about this:
val = x[x.keys()[0]]
or alternatively:
val = x.values()[0]
and then your answer is
len(val)
Some of the other solutions (posted by thefourtheye and gnibbler) are better because they are not creating an intermediate list. I added this response merely as an easy to remember and obvious option, not a solution for time-efficient usage.
Works ok in Python2 or Python3
>>> x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
>>> next(len(i) for i in x.values())
2
This is better for Python2 as it avoids making a list of the values. Works well in Python3 too
>>> next(len(x[k]) for k in x)
2
Using next and iter:
>>> x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
>>> val = next(iter(x.values()), None) # Use `itervalues` in Python 2.x
>>> val
[{'q': 2, 'p': 1}, {'q': 5, 'p': 4}]
>>> len(val)
2
>>> x = {}
>>> val = next(iter(x.values()), None) # `None`: default value
>>> val is None
True
>>> x = {'a':[{'p':1, 'q':2}, {'p':4, 'q':5}], 'b':[{'p':6, 'q':1}, {'p':10, 'q':12}]}
>>> len(x.values()[0])
2
Here, x.values gives you a list of all values then you can get length of any one value from it.

Categories