Count the number of values in each dictionary key including one value - python

I have a dict with 200e3 integer keys that have either one or two values each (strings).
I need to write logic that checks if each key has more than one value, if so add to a list.
my_dict = defaultdict(list)
my_dict = {1: ['789456', '456123'], 2: '123456', 3: '987654'}
final = []
This is what my initial solution. This works for two values, but returns the length of characters when only one value exists.
for key, value in my_dict.items():
if len(value) > 1:
final.append(key)
else:
continue
I tried enumerate but it only returns the range.
for x in enumerate(my_dict.items()):
print(x)
I came up with this solution but I'm not sure if there would be any issues with defaultdict(list) being used. Or if there's a larger issue I might not be seeing.
for key, value in my_dict.items():
if isinstance(value, list):
final.append(key)
else:
continue

Please try this:
final = [k for k,v in my_dict.items() if type(v) == list and len(v) > 1]
or in your code:
for key, value in my_dict.items():
# only this additional condition is present before `and`
if type(value) == list and len(value) > 1:
final.append(key)
Here, both '34534' and ['534', '456465'] are iterables and len() function works for both of them hence, we need to check the type of the value and only check length in case of the list.

Related

Get key by more than one value in dictionary?

Maybe the dict is not intended to be used in this way, but I need to add more than one value to the same key. My intension is to use a kind of transitory property. If my dict is A:B and B:C, than I want to have the dict A:[B,C].
Let's make an example in order to explain better what I'd like to do:
numDict={'60':['4869'], '4869':['629'], '13':['2']}
I want it to return:
{'60':['4869','629'], '13':['2']}
For just two elements, it is possible to use something like this:
result={}
for key in numDict.keys():
if [key] in numDict.values():
result[list(numDict.keys())[list(numDict.values()).index([key])]]=[key]+numDict[key]
But what about if I have more elements? For example:
numDict={'60':['4869'], '4869':['629'], '13':['2'], '629':['427'}
What can I do in order to get returned {'60':[4869,629,427'], '13':['2']}?
def unchain(d):
#assemble a collection of keys that are not also values. These will be the keys of the final dict.
top_level_keys = set(d.keys()) - set(d.values())
result = {}
for k in top_level_keys:
chain = []
#follow the reference chain as far as necessary.
value = d[k]
while True:
if value in chain: raise Exception("Referential loop detected: {} encountered twice".format(value))
chain.append(value)
if value not in d: break
value = d[value]
result[k] = chain
return result
numDict={'60':'4869', '4869':'629', '13':'2', '629':'427'}
print(unchain(numDict))
Result:
{'60': ['4869', '629', '427'], '13': ['2']}
You might notice that I changed the layout of numDict since it's easier to process if the values aren't one-element lists. But if you're dead set on keeping it that way, you can just add d = {k:v[0] for k,v in d.items()} to the top of unchain, to convert from one to the other.
You can build your own structure, consisting of a reverse mapping of (values, key), and a dictionary of (key, [values]). Adding a key, value pair consists of following a chain of existing entries via the reverse mapping, until it finds the correct location; in case it does not exist, it introduces a new key entry:
class Groupir:
def __init__(self):
self.mapping = {}
self.reverse_mapping = {}
def add_key_value(self, k, v):
self.reverse_mapping[v] = k
val = v
key = k
while True:
try:
self.reverse_mapping[val]
key = val
val = self.reverse_mapping[val]
except KeyError:
try:
self.mapping[val].append(v)
except KeyError:
self.mapping[val] = [v]
break
with this test client:
groupir = Groupir()
groupir.add_key_value(60, 4869)
print(groupir.mapping)
groupir.add_key_value(4869, 629)
print(groupir.mapping)
groupir.add_key_value(13, 2)
print(groupir.mapping)
groupir.add_key_value(629, 427)
print(groupir.mapping)
outputs:
{60: [4869]}
{60: [4869, 629]}
{60: [4869, 629], 13: [2]}
{60: [4869, 629, 427], 13: [2]}
Restrictions:
Cycles as mentioned in comments.
Non unique keys
Non unique values
Probably some corner cases to take care of.
I have written a code for it. See if it helps.
What I have done is to go on diving in till i can go (hope you understand this statement) and mark them as visited as they will no longer be required. At the end I filter out the root keys.
numDict={'60':['4869'], '4869':['629'], '13':['2'], '629':['427']}
l = list(numDict) # list of keys
l1 = {i:-1 for i in numDict} # to track visited keys (initialized to -1 initially)
for i in numDict:
# if key is root and diving in is possible
if l1[i] == -1 and numDict[i][0] in l:
t = numDict[i][0]
while(t in l): # dive deeper and deeper
numDict[i].extend(numDict[t]) # update the value of key
l1[t] = 1 # mark as visited
t = numDict[t][0]
# filter the root keys
answer = {i:numDict[i] for i in numDict if l1[i] == -1}
print(answer)
Output:
{'60': ['4869', '629', '427'], '13': ['2']}

Python - remove certain values from a dictionary and then return it

I am trying to remove certain values from a dict and return it.
For example, if the dict contains a value that is a string with a length less than 6 it would be removed from the dict. How can I iterate through the dict and return it in its edited state?
Well, if you're just removing values that have a length less than 6, all you need is this:
d = {'a': 'asdfasdf', 'b': 'asdf'}
while True:
flag = True
for i in d:
if len(d[i]) < 6:
del d[i]
flag = False
break
if flag:
break
print d
{'a': 'asdfasdf'}
when working with dict it is good to use items():
lets consider d = {1: "myname", 2:"mynamex", 3:"mynamey",4:"name"}
for key, value in d.items():
if len(value) < 6:
del d[key]
print(d)
Ans: strings less than 6 chars are deleted
{1: 'myname', 2: 'mynamex', 3: 'mynamey'}
Note:
Python 2:
for key, value in d.iteritems():
Python 3:
for key, value in d.items()
This can end done in a single line with so called dict comprehension:
{k:v for k,v in d.items() if len(v)<6}
Internally it will unwrapped into a cycle but it's easier and less space to make a typo.
You may use diffefent conditions in loop or even make for in for.
We can do it using single loop,
def doAct(s):
for key in s.keys():
if len(s[key]) < 6:
del s[key]
return s
if you use for key in s, you will get error RuntimeError: dictionary changed size during iteration.

skip to next item in dictionary

I have nested for loops, i think this is making things complicated here.
Here is the dict i have
dict1 = {'1': '##', '2': '##'}
I am looping through this dict and here is the code
for key,value in dict1.items():
###some code ###
if ##condition is true move to next key in the for loop which is '2'##
dict1.next()
I have used dict1.next(). But this is throwing an error "dict' object has no attribute 'next'"
Even tried dict1[key] += 1 and dict1[key] = dict1.setdefault(key, 0) + 1
I understand when skipping to next key in dictionary we have to refer index of key to move on to next item. But no luck with anything and I m not sure using "continue" would fulfil my purpose, because currently I have only one value for each corresponding key ("continue" works if it so), but I want to use this code even if each key had more than one value respectively. Such that "If" condition is true for key 1 and its first corresponding value, the next iteration should be for key 2 and its values respectively.
Sorry for long story
what's wrong with using continue?
dict1 = {'1': [1,4,7], '2': '##'}
for key in dict1.keys():
if key == "1":
continue
else:
print key, dict1[key]
>>> '2 ##'
You can have the nexy key with the following:
keys = dict1.keys()
n = len(keys)
for i in range(n):
thisKey = keys[i]
if some_condition():
nextKey = keys[(i + 1) % n]
nextValue = dict1[nextKey]
print thisKey, nextValue
You have a list of keys, you iterate over the length of the keys.
If your condition is true, you can extract the next key and value.

How can you print a key given a value in a dictionary for Python?

For example lets say we have the following dictionary:
dictionary = {'A':4,
'B':6,
'C':-2,
'D':-8}
How can you print a certain key given its value?
print(dictionary.get('A')) #This will print 4
How can you do it backwards? i.e. instead of getting a value by referencing the key, getting a key by referencing the value.
I don't believe there is a way to do it. It's not how a dictionary is intended to be used...
Instead, you'll have to do something similar to this.
for key, value in dictionary.items():
if 4 == value:
print key
In Python 3:
# A simple dictionary
x = {'X':"yes", 'Y':"no", 'Z':"ok"}
# To print a specific key (for instance the 2nd key which is at position 1)
print([key for key in x.keys()][1])
Output:
Y
The dictionary is organized by: key -> value
If you try to go: value -> key
Then you have a few problems; duplicates, and also sometimes a dictionary holds large (or unhashable) objects which you would not want to have as a key.
However, if you still want to do this, you can do so easily by iterating over the dicts keys and values and matching them as follows:
def method(dict, value):
for k, v in dict.iteritems():
if v == value:
yield k
# this is an iterator, example:
>>> d = {'a':1, 'b':2}
>>> for r in method(d, 2):
print r
b
As noted in a comment, the whole thing can be written as a generator expression:
def method(dict, value):
return (k for k,v in dict.iteritems() if v == value)
Python versions note: in Python 3+ you can use dict.items() instead of dict.iteritems()
target_key = 4
for i in dictionary:
if dictionary[i]==target_key:
print(i)
Within a dictionary if you have to find the KEY for the highest VALUE please do the following :
Step 1: Extract all the VALUES into a list and find the Max of list
Step 2: Find the KEY for the particular VALUE from Step 1
The visual analyzer of this code is available in this link : LINK
dictionary = {'A':4,
'B':6,
'C':-2,
'D':-8}
lis=dictionary.values()
print(max(lis))
for key,val in dictionary.items() :
if val == max(lis) :
print("The highest KEY in the dictionary is ",key)
I think this is way easier if you use the position of that value within the dictionary.
dictionary = {'A':4,
'B':6,
'C':-2,
'D':-8}
# list out keys and values separately
key_list = list(dictionary.keys())
val_list = list(dictionary.values())
# print key with val 4
position = val_list.index(4)
print(key_list[position])
# print key with val 6
position = val_list.index(6)
print(key_list[position])
# one-liner
print(list(my_dict.keys())[list(my_dict.values()).index(6)])
Hey i was stuck on a thing with this for ages, all you have to do is swap the key with the value e.g.
Dictionary = {'Bob':14}
you would change it to
Dictionary ={1:'Bob'}
or vice versa to set the key as the value and the value as the key so you can get the thing you want

How to print a dictionary's key?

I would like to print a specific Python dictionary key:
mydic = {}
mydic['key_name'] = 'value_name'
Now I can check if mydic.has_key('key_name'), but what I would like to do is print the name of the key 'key_name'. Of course I could use mydic.items(), but I don't want all the keys listed, merely one specific key. For instance I'd expect something like this (in pseudo-code):
print "the key name is", mydic['key_name'].name_the_key(), "and its value is", mydic['key_name']
Is there any name_the_key() method to print a key name?
Edit:
OK, thanks a lot guys for your reactions! :) I realise my question is not well formulated and trivial. I just got confused because I realised 'key_name' and mydic['key_name'] are two different things and I thought it would be incorrect to print the 'key_name' out of the dictionary context. But indeed I can simply use the 'key_name' to refer to the key! :)
A dictionary has, by definition, an arbitrary number of keys. There is no "the key". You have the keys() method, which gives you a python list of all the keys, and you have the iteritems() method, which returns key-value pairs, so
for key, value in mydic.iteritems() :
print key, value
Python 3 version:
for key, value in mydic.items() :
print (key, value)
So you have a handle on the keys, but they only really mean sense if coupled to a value. I hope I have understood your question.
Additionally you can use....
print(dictionary.items()) #prints keys and values
print(dictionary.keys()) #prints keys
print(dictionary.values()) #prints values
Hmm, I think that what you might be wanting to do is print all the keys in the dictionary and their respective values?
If so you want the following:
for key in mydic:
print "the key name is" + key + "and its value is" + mydic[key]
Make sure you use +'s instead of ,' as well. The comma will put each of those items on a separate line I think, where as plus will put them on the same line.
dic = {"key 1":"value 1","key b":"value b"}
#print the keys:
for key in dic:
print key
#print the values:
for value in dic.itervalues():
print value
#print key and values
for key, value in dic.iteritems():
print key, value
Note:In Python 3, dic.iteritems() was renamed as dic.items()
The name of the key 'key_name' is 'key_name', therefore
print('key_name')
or whatever variable you have representing it.
In Python 3:
# A simple dictionary
x = {'X':"yes", 'Y':"no", 'Z':"ok"}
# To print a specific key (for example key at index 1)
print([key for key in x.keys()][1])
# To print a specific value (for example value at index 1)
print([value for value in x.values()][1])
# To print a pair of a key with its value (for example pair at index 2)
print(([key for key in x.keys()][2], [value for value in x.values()][2]))
# To print a key and a different value (for example key at index 0 and value at index 1)
print(([key for key in x.keys()][0], [value for value in x.values()][1]))
# To print all keys and values concatenated together
print(''.join(str(key) + '' + str(value) for key, value in x.items()))
# To print all keys and values separated by commas
print(', '.join(str(key) + ', ' + str(value) for key, value in x.items()))
# To print all pairs of (key, value) one at a time
for e in range(len(x)):
print(([key for key in x.keys()][e], [value for value in x.values()][e]))
# To print all pairs (key, value) in a tuple
print(tuple(([key for key in x.keys()][i], [value for value in x.values()][i]) for i in range(len(x))))
Since we're all trying to guess what "print a key name" might mean, I'll take a stab at it. Perhaps you want a function that takes a value from the dictionary and finds the corresponding key? A reverse lookup?
def key_for_value(d, value):
"""Return a key in `d` having a value of `value`."""
for k, v in d.iteritems():
if v == value:
return k
Note that many keys could have the same value, so this function will return some key having the value, perhaps not the one you intended.
If you need to do this frequently, it would make sense to construct the reverse dictionary:
d_rev = dict(v,k for k,v in d.iteritems())
Update for Python3: d.iteritems() is not longer supported in Python 3+ and should be replaced by d.items()
d_rev = {v: k for k, v in d.items()}
# highlighting how to use a named variable within a string:
mapping = {'a': 1, 'b': 2}
# simple method:
print(f'a: {mapping["a"]}')
print(f'b: {mapping["b"]}')
# programmatic method:
for key, value in mapping.items():
print(f'{key}: {value}')
# yields:
# a 1
# b 2
# using list comprehension
print('\n'.join(f'{key}: {value}' for key, value in dict.items()))
# yields:
# a: 1
# b: 2
Edit: Updated for python 3's f-strings...
Make sure to do
dictionary.keys()
rather than
dictionary.keys
import pprint
pprint.pprint(mydic.keys())
Or you can do it that manner:
for key in my_dict:
print key, my_dict[key]
dict = {'name' : 'Fred', 'age' : 100, 'employed' : True }
# Choose key to print (could be a user input)
x = 'name'
if x in dict.keys():
print(x)
What's wrong with using 'key_name' instead, even if it is a variable?
Probably the quickest way to retrieve only the key name:
mydic = {}
mydic['key_name'] = 'value_name'
print mydic.items()[0][0]
Result:
key_name
Converts the dictionary into a list then it lists the first element which is the whole dict then it lists the first value of that element which is: key_name
I'm adding this answer as one of the other answers here (https://stackoverflow.com/a/5905752/1904943) is dated (Python 2; iteritems), and the code presented -- if updated for Python 3 per the suggested workaround in a comment to that answer -- silently fails to return all relevant data.
Background
I have some metabolic data, represented in a graph (nodes, edges, ...). In a dictionary representation of those data, keys are of the form (604, 1037, 0) (representing source and target nodes, and the edge type), with values of the form 5.3.1.9 (representing EC enzyme codes).
Find keys for given values
The following code correctly finds my keys, given values:
def k4v_edited(my_dict, value):
values_list = []
for k, v in my_dict.items():
if v == value:
values_list.append(k)
return values_list
print(k4v_edited(edge_attributes, '5.3.1.9'))
## [(604, 1037, 0), (604, 3936, 0), (1037, 3936, 0)]
whereas this code returns only the first (of possibly several matching) keys:
def k4v(my_dict, value):
for k, v in my_dict.items():
if v == value:
return k
print(k4v(edge_attributes, '5.3.1.9'))
## (604, 1037, 0)
The latter code, naively updated replacing iteritems with items, fails to return (604, 3936, 0), (1037, 3936, 0.
I looked up this question, because I wanted to know how to retrieve the name of "the key" if my dictionary only had one entry. In my case, the key was unknown to me and could be any number of things. Here is what I came up with:
dict1 = {'random_word': [1,2,3]}
key_name = str([key for key in dict1]).strip("'[]'")
print(key_name) # equal to 'random_word', type: string.
Try this:
def name_the_key(dict, key):
return key, dict[key]
mydict = {'key1':1, 'key2':2, 'key3':3}
key_name, value = name_the_key(mydict, 'key2')
print 'KEY NAME: %s' % key_name
print 'KEY VALUE: %s' % value
key_name = '...'
print "the key name is %s and its value is %s"%(key_name, mydic[key_name])
If you want to get the key of a single value, the following would help:
def get_key(b): # the value is passed to the function
for k, v in mydic.items():
if v.lower() == b.lower():
return k
In pythonic way:
c = next((x for x, y in mydic.items() if y.lower() == b.lower()), \
"Enter a valid 'Value'")
print(c)

Categories