creating dictionary where value is key using comprehension - python

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

Related

Ordering the values of a dictionary with a for loop iteration

I'm a Python Newb and trying to create a dictionary with ordered values.
Since dict.fromkeys only allows me to copy the same value for each key, I've set all values to 0 and tried something like this:
def Ord_Values_in_Dic(D):
c = 0
for value in D.values():
c += 1
value += c
return D
My output only changes the first value of the dictionary to 1 though, instead I'd want the second value to also change to 2, the third value to change to 3 and so on...
I don't get if the loop isn't iterating correctly through the dictionary or there's something else wrong.
Since dict.fromkeys only allows me to copy the same value for each key
then it is not right tool for you task. You might use zip to prepare dict from 2 iterables - one for keys, one for values, consider following simple example
keys = ["x","y","z"]
d = dict(zip(keys,range(3)))
print(d) # {'x': 0, 'y': 1, 'z': 2}
range with single arguments gives subsequent numbers from 0 (inclusive) to given value (exclusive), so in above example: 0,1,2
Got it!
import numpy as np
a = np.linspace(0,100,100)
b = np.sin(a)
c = np.cos(a)
idx = list(range(1,101))
X = dict(zip(b, idx))
Y = dict(zip(c, idx))
This solved it!
Thank you :)

How to get max() to return variable names instead of values in Python?

So I would like to get the maximum value from 3 variables, x,y,z.
x = 1
y = 2
z = 3
max(x, y, z) # returns 3 but I want "z"
However this returns the value of z i.e 3. How do I get the name of the variable e.g. "z" instead?
Thanks
Make a dictionary and then use max. Also works with min. It will return you the variable name in the form of string.
>>> x = 1
>>> y = 2
>>> z = 3
>>> var = {x:"x",y:"y",z:"z"}
>>> max(var)
3
>>> var.get(max(var))
'z'
>>> var.get(min(var))
'x'
>>>
You could put them into a dictionary and use max with a key:
dict1 = {'x':1, 'y':2, 'z':3}
max(dict1, key=dict1.get)
But think through the ramifications of this. What if you have the same val multiple times, and other edge cases.
Use a dictionary and get the maximum of its items, using a key function.
d = {'x':1, 'y':2, 'z':3}
max(d.items(), key=lambda i: i[1])
This is not at all recommended but you can use the globals() dictionary which keeps track of all variables that are either built-ins or have been defined by the user:
x = 1
y = 2
z = 3
variables = {k: v for k, v in globals().items() if isinstance(v, int)}
max_value = max(variables.values())
res = next(k for k, v in variables.items() if v == max_value)
which results in:
print(res) # z
Create a List of the numbers then type max() around the list.

Finding if there are distinct elements in a python dictionary

I have a python dictionary containing n key-value pairs, out of which n-1 values are identical and 1 is not. I need to find the key of the distinct element.
For example: consider a python list [{a:1},{b:1},{c:2},{d:1}]. I need the to get 'c' as the output.
I can use a for loop to compare consecutive elements and then use two more for loops to compare those elements with the other elements. But is there a more efficient way to go about it or perhaps a built-in function which I am unaware of?
If you have a dictionary you can quickly check and find the first value which is different from the next two values cycling around the keys of your dictionary.
Here's an example:
def find_different(d):
k = d.keys()
for i in xrange(0, len(k)):
if d[k[i]] != d[k[(i+1)%len(k)]] and d[k[i]] != d[k[(i+2)%len(k)]]:
return k[i]
>>> mydict = {'a':1, 'b':1, 'c':2, 'd':1}
>>> find_different(mydict)
'c'
Otherwise, if what you have is a list of single-key dictionaries, then you can do it quite nicely mapping your list with a function which "extracts" the values from your elements, then check each one using the same logic.
Here's another working example:
def find_different(l):
mask = map(lambda x: x[x.keys()[0]], l)
for i in xrange(0, len(l)):
if mask[i] != mask[(i+1)%len(l)] and mask[i] != mask[(i+2)%len(l)]:
return l[i].keys()[0]
>>> mylist = [{'a':1},{'b':1},{'c':2},{'d':1}]
>>> find_different(mylist)
'c'
NOTE: these solutions do not work in Python 3 as the map function doesn't return a list and neither does the .keys() method of dictionaries.
Assuming that your "list of pairs" (actually list of dictionaries, sigh) cannot be changed:
from collections import defaultdict
def get_pair(d):
return (d.keys()[0], d.values()[0])
def extract_unique(l):
d = defaultdict(list)
for key, value in map(get_pair, l):
d[value].append(key)
return filter(lambda (v,l): len(l) == 1, d.items())[0][1]
If you already have your dictionary, then you make a list of all of the keys: key_list = yourDic.keys(). Using that list, you can then loop through your dictionary. This is easier if you know one of the values, but below I assume that you do not.
yourDic = {'a':1, 'b':4, 'c':1, 'd':1, }
key_list = yourDic.keys()
previous_value = yourDic[key_list[0]] # Making it so loop gets past first test
count = 0
for key in key_list:
test_value = yourDic[key]
if (test_value != previous_value) and count == 1: # Checks first key
print key_list[count - 1]
break
elif (test_value != previous_value):
print key
break
else:
previous_value = test_value
count += 1
So, once you find the value that is different, it will print the key. If you want it to print the value, too, you just need a print test_value statement

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