if statement doesn't work properly in python - python

d={1:'a', 2:'b', 3:'c', 4:'a', 5:'d', 6:'e', 7:'a', 8:'b'}
value = raw_input("Choose a value to be searched: ")
data = ""
if value in d:
data = d.keys["value"]
print(data)
else:
print "There isn't such value in the dictionary"
So I write 'a' and I want to get the key '1'
but it skips "data = d.keys["value"] print(data)" and it prints me the message of "else"
What have I done wrong?

Containment checks for dict check the keys, not the values, and 'a' is a value in the dict, not a key.
The simplest fix would be to change your test to:
if value in d.viewvalues(): # d.values() on Python 3
but that's still sub-optimal; you can't perform efficient (O(1)) lookups in the values of a dict (nor can you do d.keys[value] as you seem to think you can; you'd have to perform a second linear scan to find the key, or perform a more complicated single scan to determine if the value exists and pull the key at the same time).
Really though, it seems like you want your dictionary reversed, with the keys as values and vice-versa. Doing it this way:
d = {1:'a', 2:'b', 3:'c', 4:'a', 5:'d', 6:'e', 7:'a', 8:'b'}
d_inv = {v: k for k, v in d.items()} # Make inverted version of d
value = raw_input("Choose a value to be searched: ")
if value in d_inv:
data = d_inv[value]
print(data)
else:
print "There isn't such value in the dictionary"
you can perform the containment check and lookup efficiently (if d isn't otherwise needed, you can just replace d with the same structure as d_inv and use d instead of d_inv uniformly).

As stated, you need the value, here's an alternative
if any(d[value] for value in d):
Then, d.keys["value"] is actually d[value]

You could do something like this:
d={1:'a', 2:'b', 3:'c', 4:'a', 5:'d', 6:'e', 7:'a', 8:'b'}
value = 'q'
data = [key for key, val in d.items() if val == value]
if len(data) > 0:
print(data)
else:
print "There isn't such value in the dictionary"
Then you would get the results
[1, 4, 7]

Related

Merge two dictionaries' values by keys

Hi I want to merge two dictionaries' values if the keys are the same.
DIC_01
{'A': ['Zero'],
'B': ['Zero'],
'C': ['Zero'],
'D': ['Zero']}
DIC_02
{'A': [2338.099365234375,
-3633.070068359375,
-73.45938873291016],
'D':[2839.291015625,
-2248.350341796875,
1557.59423828125]}
Idea output
{'A': [[2338.099365234375,
-3633.070068359375,
-73.45938873291016],['Zero']],
'D': [[2839.291015625,
-2248.350341796875,
1557.59423828125]['Zero']]}
Output for the Keys that cannot be found
{'B': ['Zero'],'C': ['Zero']}
I tried
NO_MATCH={}
for k in DIC_01.keys():
DOC={}
for k2 in DIC_02.keys():
if k == k2:
DOC = k.values().update(k2.values())
else:
NO_MATCH.update(DIC_01)
There is nothing in DOC and all the dictionary elements are in NO_MATCH, no error message. don't know where goes wrong, also I think there must be better ways to do this.
Thank you!
Edited: You can declare two separate dictionaries and iterate through all the keys of both dictionaries. For every iteration, check if the key exists in DIC_02 and DIC_01 and concatenate the two corresponding lists
match, no_match = {}, {}
for i in {**DIC_01,**DIC_02}.keys():
if i in DIC_01 and i in DIC_02:
match[i] = DIC_01[i] + DIC_02[i]
else:
no_match[i] = DIC_01.get(i,[]) + DIC_02.get(i,[])
It's not particularly fancy but this should solve what you're looking for
def merge(a, b):
out = {}
for key in a.keys() | b.keys():
if key in a and key in b:
out[key] = [a[key], b[key]]
elif key in a:
out[key] = a[key]
else:
out[key] = b[key]
return out
where a and b are dicts. The | takes the union of the two key sets.
As for why your code goes wrong.
NO_MATCH={}
for k in DIC_01.keys():
DOC={} # (1)
for k2 in DIC_02.keys(): # (2)
if k == k2:
DOC = k.values().update(k2.values()) # (3)
else:
NO_MATCH.update(DIC_01) # (4)
Not there! Everything you define inside a loop, will be redefined everytime the loop goes around.
This goes to the else block even if there's a matched key. For instance, in your case, it compares A in DIC_01 with A in DIC_02, "ok, A matched". BUT, then it proceeds to compare A in DIC_01 with D in DIC_02, "ok, A not found in DIC_02, not matched, add to NOT_MATCH" which is wrong, because A IS a matched key and A IS in DIC_02.
Not sure how you didn't get an error, seems very erroneous.
This lines add the entire DIC_01 to NO_MATCH, wrong!
FIX:
MATCH = {}
NO_MATCH = {}
# This goes through all keys in DIC_01. If a key is also found in DIC_02,
# it's a "matched" key so it adds that key to the MATCH variable. If it's
# not in DIC_02, it's a "no matched" key -> add key to NO_MATCH variable.
for k in DIC_01.keys():
if k in DIC_02.keys():
MATCH[k] = [DIC_01[k], DIC_02[k]]
else:
NO_MATCH[k] = DIC_01[k]
# BUT...We are still missing the keys that are only in DIC_02. So we need
# another loop
for k in DIC_02.keys():
if k not in DIC_01.keys():
NO_MATCH[k] = DIC_02[k]
# This is the same as the loop above, without the if block.
BETTER WAY
Some list comprehensions would keep things clean.
MATCH = {key:[DIC_01[key], DIC_02[key]] for key in DIC_01 if key in DIC_02}
unmatch_1 = {key:DIC_01[key] for key in DIC_01 if key not in DIC_02}
unmatch_2 = {key:DIC_02[key] for key in DIC_02 if key not in DIC_01}
NOT_MATCH = {**unmatch_1, **unmatch_2}
EXPLAINATION:
MATCH = {key:[DIC_01[key], DIC_02[key]] for key in DIC_01 if key in DIC_02}
This, in English, create a new dictionary called match.For every key in DIC_01, if the key is also in DIC_02, create the same key in match and assign both the values of that key from DIC_01 and DIC_02.
unmatch_1 = {key:DIC_01[key] for key in DIC_01 if key not in DIC_02}
This ... For every key in DIC_01, if it's not in DIC_02, create a key and assign the associated value from DIC_01
unmatch_2 = {key:DIC_02[key] for key in DIC_02 if key not in DIC_01}
This ... For every key in DIC_02, if it's not in DIC_01, create a key and assign the associated value from DIC_02
UNMATCH = {**unmatch_1, **unmatch_2}
This ... is a cool way of merging 2 dictionaries (Only for Python 3.5 and up)
This looks like a great use for ChainMap
>>> a={'A': ['Zero'],
... 'B': ['Zero'],
... 'C': ['Zero'],
... 'D': ['Zero']}
>>> b={'A': [2338.099365234375,
... -3633.070068359375,
... -73.45938873291016],
... 'D':[2839.291015625,
... -2248.350341796875,
... 1557.59423828125]}
>>> map=ChainMap(b,a)
>>> map['A']
[2338.099365234375, -3633.070068359375, -73.45938873291016]
>>> map['C']
['Zero']
The key precedence will be on the order of the dictionaries, so if you can't control order or if the ['Zero'] are mixed and matched: this way can't help.

How to Get a Key value from a dictionary whose values are lists?

I have a dictionary where each key has several lists of data as its values like this
myDict = {'data1' : ['data_d','dataD']['data_e','dataE']['data_f','dataF']}
I want to be able to input one of the values in the list and then be given the key. This is so I can get the other value in the list now that I have the key.
I've tried
dataKey = (list(myDict.keys())[list(myDict.values()).index(dataD)])
but that didn't work
I've also tried
for k, v in myDict.items():
if 'dataD' in v:
print k
but that didn't work as well.
Side question, in the questions that I've looked through, I see people using the variable k and v a lot even without the OP mentioning them, so I am wondering if k and v are already set variable in dictionaries?
Your second attempt was almost right, but a nested for loop is needed to traverse the list-of-lists:
myDict = {'data1' : [['data_d','dataD'], ['data_e','dataE'], ['data_f','dataF']]}
for key, value in myDict.items():
for sublist in value:
if 'dataD' in sublist:
print(key) # -> data1
Using variables named k, and v with dictionaries is purely optional and aren't special properties—other than being very short abbreviations for "key" and "value".
Note that if only one match is ever expected to occur, the code could be made more efficient by stopping the search after one is found. Here's one way of doing that:
target = 'dataD'
try:
for key, value in myDict.items():
for sublist in value:
if target in sublist:
print(key) # -> data1
raise StopIteration # found, so quit searching
except StopIteration:
pass # found
else:
print('{} not found'.format(target))
if they are all going to be lists then you can do something like this (if i am understanding correctly)
myDict = {
'data1': [['data_d','dataD'], ['data_e','dataE'], ['data_f','dataF']],
}
def find(dic, item):
for k, v in dic.items():
for ls in v:
if item in ls:
return k
return False
print(find(myDict, "data_d"))
# OUT [data1]

Adding nonzero items from a dictionary to another dictionary

I have a set of reactions (keys) with values (0.0 or 100) stored in mydict.
Now I want to place non zero values in a new dictionary (nonzerodict).
def nonzero(cmod):
mydict = cmod.getReactionValues()
nonzerodict = {}
for key in mydict:
if mydict.values() != float(0):
nonzerodict[nz] = mydict.values
print nz
Unfortunately this is not working.
My questions:
Am I iterating over a dictionary correctly?
Am I adding items to the new dictionary correctly?
You are testing if the list of values is not equal to float(0). Test each value instead, using the key to retrieve it:
if mydict[key] != 0:
nonzerodict[key] = mydict[key]
You are iterating over the keys correctly, but you could also iterate over the key-value pairs:
for key, value in mydict.iteritems():
if value != 0:
nonzerodict[key] = value
Note that with floating point values, chances are you'll have very small values, close to zero, that you may want to filter out too. If so, test if the value is close to zero instead:
if abs(value) > 1e-9:
You can do the whole thing in a single dictionary expression:
def nonzero(cmod):
return {k: v for k, v in cmod.getReactionValues().iteritems() if abs(v) > 1e-9}
Its simple and you can it by below way -
>>> d = {'a':4,'b':2, 'c':0}
>>> dict((k,v) for k,v in d.iteritems() if v!=0)
{'a': 4, 'b': 2}
>>>
Replace if condition in you code with:
if mydict[key]:
nonzerodict[key] = mydict[key]
Your solution can be further simplified as:
def nonzero(cmod):
mydict = cmod.getReactionValues()
nonzerodict = {key: value for key, value in mydict.iteritems() if value}

How to check if a key/value is repeated elsewhere in a dictionary using Python

I have a dictionary in python like:
dict = {'dog':['milo','otis','laurel','hardy'],
'cat':['bob','joe'],
'milo':['otis','laurel','hardy','dog'],
'hardy':['dog'],'bob':['joe','cat']}
...and I want to identify if a key exists elsewhere in a dictionary (in some other list of values). There are other questions I could find that want to know if an item simply exists in the dictionary, but this is not my question. The same goes for items in each list of values, to identify items that do not exist in OTHER keys and their associated values in the dictionary.
In the above example, the idea is that dogs and cats are not equal, their keys/values have nothing in common with those that come from cats. Ideally, a second dictionary would be created that collects all of those associated with each unique cluster:
unique.dict = {'cluster1':['dog','milo','otis','laurel','hardy'],
'cluster2':['cat','bob','joe'] }
This is a follow up question to In Python, count unique key/value pairs in a dictionary
It appears that the relationship is symmetric, but your data is not (e.g. there is no key 'otis'). The first part involves making it symmetric, so it won't matter where we start.
(If your data actually is symmetric, then skip that part.)
Python 2.7
from collections import defaultdict
data = {'dog':['milo','otis','laurel','hardy'],'cat':['bob','joe'],'milo':['otis','laurel','hardy','dog'],'hardy':['dog'],'bob':['joe','cat']}
# create symmetric version of data
d = defaultdict(list)
for key, values in data.iteritems():
for value in values:
d[key].append(value)
d[value].append(key)
visited = set()
def connected(key):
result = []
def connected(key):
if key not in visited:
visited.add(key)
result.append(key)
map(connected, d[key])
connected(key)
return result
print [connected(key) for key in d if key not in visited]
Python 3.3
from collections import defaultdict
data = {'dog':['milo','otis','laurel','hardy'],'cat':['bob','joe'],'milo':['otis','laurel','hardy','dog'],'hardy':['dog'],'bob':['joe','cat']}
# create symmetric version of data
d = defaultdict(list)
for key, values in data.items():
for value in values:
d[key].append(value)
d[value].append(key)
visited = set()
def connected(key):
visited.add(key)
yield key
for value in d[key]:
if key not in visited:
yield from connected(value)
print([list(connected(key)) for key in d if key not in visited])
Result
[['otis', 'milo', 'laurel', 'dog', 'hardy'], ['cat', 'bob', 'joe']]
Performance
O(n), where n is the total number of keys and values in data (in your case, 17 if I count correctly).
I'm taking "in some other list of values" literally, to mean that a key existing in its own set of values is OK. If not, that would make things slightly simpler, but you should be able to adjust the code yourself, so I won't write it both ways.
If you insist on using this data structure, you have to do it by brute force:
def does_key_exist_in_other_value(d, key):
for k, v in d.items():
if k != key and key in v:
return True
You could of course condense that into a one-liner with a genexpr and any:
return any(key in v for k, v in d.items() if k != key)
But a smarter thing to do would be to use a better data structure. At the very least use sets instead of lists as your values (which wouldn't simplify your code, but would make it a lot faster—if you have K keys and V total elements across your values, it would run in O(K) instead of O(KV).
But really, if you want to look things up, build a dict to look things up in:
inv_d = defaultdict(set)
for key, value in d.items():
for v in value:
inv_d[v].add(key)
And now, your code is just:
def does_key_exist_in_other_value(inv_d, key):
return inv_d[key] != {key}

how to delete a key from a dictionary with the highest value?

I have a simple question (or so I thought).
I have a dictionary, lets say it looks like this:
dict = {'A':100, 'a':10, 'T':50, 't':5}
I simply want to delete the key with the highest value. I tried this:
del max(dict.values())
and this is the error message: 'Syntax Error: can´t delete function call'.
I want the end result to be:
dict = {'a':10, 'T':50, 't':5}
You need to get a hold of the key to the max value.
Try this instead:
del d[max(d, key=d.get)]
Also, you should avoid calling your variable dict because it shadows the built-in name.
max(d.values()) will give you the maximum value (100), but to delete an entry from a dictionary you need the corresponding key ('A').
You can do this:
d = {'A':100, 'a':10, 'T':50, 't':5}
key_to_delete = max(d, key=lambda k: d[k])
del d[key_to_delete]
By the way, you shouldn't name your dictionary dict because that's the name of a built-in type.
If there may be multiple entries with the same maximum value and you want to delete all of them:
val_to_delete = max(d.values())
keys_to_delete = [k for k,v in d.iteritems() if v==val_to_delete]
for k in keys_to_delete:
del d[k]

Categories

Resources