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]
Related
I'm trying to generate a dictionary where value is a list using following dictionary of comprehension method.
>>> x = ['a','b','c']
>>> y = {'a':1,'b':2}
>>> z = {i:[].append(j) for (i,j) in y.items() if i in x and j < 2}
>>> z
{'a': None}
I'm trying to get:
{'a':[1]}
Can someone please let me know how to do that? I think I'm getting None as value as it is acting as function and returning None.
Code
x = ['a','b','c']
y = {'a':1,'b':2}
z = {key: [y[key]] for key in list(y.keys()) if key in x and y[key] < 2}
print(z)
output:
{'a': [1]}
Explaination
i get every key from y with list(y.keys())
if they key is in x i continue else i skip to next key
if above condition is satisfied i control if the key value in y is smalller than 2
if also the above condition is satisfied i create a new item in z with key as key and a list containing y value as value
the error rin your code was just that [].append(j) returned None so you only ad to do:
z = {i:[j] for (i,j) in y.items() if i in x and j < 2}
another weird thing is to create a list for j that is a single value, but, becaouse you required it in your expected output and you have surely your reasons to do that, i keeped the output as you wanted, but in general if it is a single value is better to store it directly in the dictand not create a nested list for it in a dict
I've been working on a solution for an assignment where we which accepts a list of tuple objects and returns a dictionary containing the frequency of all the strings that appear in the list
So I've been trying to use Counter from collections to count the frequency of a key that is occurring inside a tuple list
tuple_list = [('a',5), ('a',5), ('b',6), ('b',4), ('b',3), ('b',7)]
I can't get the Counter to only check for 'a' or 'b' or just the strings in the list.
from collections import Counter
def get_frequency(tuple_list):
C = Counter(new_list)
print (C('a'), C('b'))
tuple_list = [('a',5), ('a',5), ('b',6), ('b',4), ('b',3), ('b',7)]
freq_dict = get_frequency(tuple_list)
for key in sorted(freq_dict.keys()):
print("{}: {}".format(key, freq_dict[key]))
The output that I was expecting should be a: 2 b: 4 but I kept on getting a: 0 b: 0
Since the second (numeric) element in each tuple appears to be irrelevant, you need to pass in a sequence of the letters you're trying to count. Try a list comprehension:
>>> tuple_list = [('a',5), ('a',5), ('b',6), ('b',4), ('b',3), ('b',7)]
>>>
>>> items = [item[0] for item in tuple_list]
>>> items
['a', 'a', 'b', 'b', 'b', 'b']
>>> from collections import Counter
>>> c = Counter(items)
>>> print(c)
Counter({'b': 4, 'a': 2})
if you don't want to use counter, you can just do the length of the lists like this...
unique_values = list(set([x[0] for x in tuple_list]))
a_dict = {}
for v in unique_values:
a_dict[v] = len([x[1] for x in tuple_list if x[0] == v])
print(a_dict)
which gives you:
{'b': 4, 'a': 2}
Since you only want to count the first element (the string) in each tuple, you should only use the counter object on that first element as you can see in the get_frequency function below:
def get_frequency(tuple_list):
cnt = Counter()
for tuple_elem in tuple_list:
cnt[tuple_elem[0]] += 1
return cnt
tuple_list = [('a',5), ('a',5), ('b',6)]
freq_dict = get_frequency(tuple_list)
for key, value in freq_dict.items():
print(f'{key}: {value}')
Also, make sure if you hope to receive a value from a function, you usually need to return a value using a return statement.
Hope that helps out!
Another solution is to use zip and next to extract the first item of each tuple into a new tuple and feed it into Counter.
from collections import Counter
result = Counter(next(zip(*items)))
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.
I am confused how python is iterating through this dictionary. From python's documentation, the itervalues returns an iterator over the dictionary's values.
dict = {"hello" : "wonderful", "today is" : "sunny", "more text" : "is always good"}
for x in dict.itervalues():
x = x[2:]
print dict
This prints out the original dictionary unchanged. Why is that? If I am saying the value at position x is "blabla", why is it not getting set?
This has nothing to do with strings or lists. The devil is in how the for is unfolded.
Doing
for x in d.iteritems():
# loop body
is more-or-less equivalent to doing
iter = d.itervalues()
while True:
try:
x = next(iter)
# loop body
except StopIteration:
break
So with this in mind it's not very hard to see that we are just reassigning x, which holds a result from a function call.
iter = d.itervalues()
while True:
try:
x = next(iter)
x = 5 # There is nothing in this line about changing the values of d
except StopIteration:
break
The only thing the line
x = x[2:]
does is creating the string slice x[2:] and rebinding the name x to point to this new string. It does not change the string x pointed to before. (Strings are immutable in Python, they can't be changed.)
To achieve what you actually want, you need to make the dictionary entry point to the new string object created by the slicing:
for k, v in my_dict.iteritems():
my_dict[k] = v[2:]
As Sven Marnach points out, strings are immutable and you are just rebinding x to a new string created by the slice notation. You can demonstrate that x does point to the same object in the dictionary by using id:
>>> obj = 'hello'
>>> id(obj)
<<< 4318531232
>>> d = {'key': obj}
>>> [id(v) for v in d.values()]
<<< [4318531232]
>>> [id(v) for v in d.itervalues()]
<<< [4318531232]
>>> [(k, id(v)) for k, v in d.items()]
<<< [('key', 4318531232)]
>>> [(k, id(v)) for k, v in d.iteritems()]
<<< [('key', 4318531232)]
You can use iteritems to iterate over key and value together to do what you want:
for k,v in dict.iteritems():
dict[k] = v[2:]
[{'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