Adding a constant integer to a value in a python dictionary - python

How would you add a constant number, say 1, to a value in a dictionary if certain conditions are fulfilled.
For example, if I had a dictionary:
dict = {'0':3, '1':3, '2':4, '3':4, '4':4}
If I simply wanted to add the integer 1 to every value in the dictionary so it updates dict as this:
dict = {'0':4, '1':4, '2':5, '3':5, '4':5}
When I used the following code where the Cur_FID is the first one in the dictionary '0', it gave me a value of 5? It should have given me 4. ??
for lucodes in gridList2: # a list of the values [3,3,4,4,4] -- have to separate out because it's part of a larger nested list
if lucodes > 1:
if lucodes < 5:
FID_GC_dict[Cur_FID] = lucodes + 1
print FID_GC_dict[Cur_FID] #returned 5??? weird
I want to add 1 to all the values, but stopped here when the first dictionary update did something weird.

One simple way to do this is to use a collections.Counter object, which you can use in every way like a normal dictionary in most ways but it is optimized for keeping a count of items:
>>> from collections import Counter
>>> d = Counter({'0':3, '1':3, '2':4, '3':4, '4':4})
>>> d
Counter({'3': 4, '2': 4, '4': 4, '1': 3, '0': 3})
>>> d.update(d.keys())
>>> d
Counter({'3': 5, '2': 5, '4': 5, '1': 4, '0': 4})
As for only doing it when certain conditions are fulfilled, just use a comprehension or generator to only pass the list of the keys you want to increment to d.update():
>>> d = Counter({'3': 4, '2': 4, '4': 4, '1': 3, '0': 3})
>>> d.update((k for k, v in d.items() if v == 4))
>>> d
Counter({'3': 5, '2': 5, '4': 5, '1': 3, '0': 3})

Another way of doing this would be to use the items() method of dictionary which returns a list of key, value tuples:
def f(dict):
for entry in dict.items():
if entry[1] > 1 and entry[1] < 5:
dict[entry[0]] = entry[1] + 1
return dict
You can then extend this to take an arbitrary function:
def f(dict, func):
for entry in dict.items():
if func(entry[1]):
dict[entry[0]] = entry[1] + 1
return dict
This can be provided a function such as:
def is_greater_than_one(x):
return x > 1
and called in the following way:
f(input_dictionary,is_greater_than_one)

Your code says the following:
for each value in [3,3,4,4,4]:
if 1 < value < 5:
FID_thingy['0'] = value + 1
So it will set FID_thingy['0'] to 4 then 4 then 5 then 5 then 5. Do you see why?

Related

How can I check that a value exists in a dictionary or not in python

mydict = {}
while True:
num = int(input())
if num == 0 :
break
while num > 0:
inp = input().split(" ")
mylist = list(inp)
for i in range(0,len(mylist)):
if mylist[i] in mydict.values():
print(f"Yes, Value: '{mylist[i]}' exists in dictionary")
else:
print(f"No, Value: '{mylist[i]}' does not exists in dictionary")
mydict[mylist[i]] = 0
print(mydict)
for i in range(0,len(mylist)):
if i == 0 :
mydict[mylist[i]] += 3
if i == 1 :
mydict[mylist[i]] += 2
if i == 2 :
mydict[mylist[i]] += 1
print(mydict)
num-=1
this is my code and I don't know why it doesn't understand that some value in the dictionary is already exist after adding them, and I don't want them to change it to zero
2
3 3 2 1
No, Value: '3' does not exists in dictionary
No, Value: '3' does not exists in dictionary
No, Value: '2' does not exists in dictionary
No, Value: '1' does not exists in dictionary
{'3': 0, '2': 0, '1': 0}
{'3': 5, '2': 1, '1': 0}
3 2 3 1
No, Value: '3' does not exists in dictionary
No, Value: '2' does not exists in dictionary
No, Value: '3' does not exists in dictionary
No, Value: '1' does not exists in dictionary
{'3': 0, '2': 0, '1': 0}
{'3': 4, '2': 2, '1': 0}
0
but I want :
2
3 3 2 1
No, Value: '3' does not exists in dictionary
No, Value: '3' does not exists in dictionary
No, Value: '2' does not exists in dictionary
No, Value: '1' does not exists in dictionary
{'3': 0, '2': 0, '1': 0}
{'3': 5, '2': 2, '1': 0}
3 2 3 1
Yes, Value: '3' exists in dictionary
Yes, Value: '2' exists in dictionary
Yes, Value: '3' exists in dictionary
Yes, Value: '1' exists in dictionary
{'3': 5, '2': 2, '1': 0}
{'3': 9, '2': 4, '1': 0}
0
Your requirements are pretty unclear but it seems that this is something you want (explanation in code comments):
# import zip_longest because it allows to zip shorter
# and longer iterators and replace the corresponding
# shorter iterator's values with None by default
from itertools import zip_longest
# define the main dictionary
dct = dict()
# this is the placement so that first
# gets added a value of 3 and so on
# this is why zip longest is needed
placement = [3, 2, 1]
# main loop
while True:
# get input and .split it
inp = input().split()
# if no input was provided
# stop the program
if not len(inp):
break
# and now for the input and the placement, zip longest them
for key, added_value in zip_longest(inp, placement):
# first check if the key is in the dictionary
if key in dct.keys():
# if the key is in dictionary print this and already add the
# corresponding value depending in which place
# the key was located in input
print(f'Key {repr(key)} is in the dictionary')
if added_value is not None:
dct[key] += added_value
# in case user input is shorter just break this, so that
# dictionary doesn't have None keys
elif key is None:
break
else:
# if the key wasn't in the dictionary set it to the
# value corresponding to placement
print(f'Key {repr(key)} is not in the dictionary')
dct[key] = added_value if added_value is not None else 0
# print the current dictionary
print(dct)

Python count elements in dictionary comprehension when count is above a threshold

I want to populate a dictionary with the counts of various items in a list, but only when the count exceeds a certain number. (This is in Python 2.7)
For example:
x = [2,3,4,2,3,5,6] if I only want numbers that appear twice or more, I would want only
d = {2: 2, 3: 2} as an output.
I wanted to do this with a dictionary comprehension, for example
{(num if x.count(num) >= 2): x.count(num) for num in x}
But this throws an "invalid syntax" error, and it seems I need to set some default key, which means some key I don't want being added to the dictionary which I then have to remove.
What I'm doing now is in two lines:
d = {(num if x.count(num) >= 2 else None): x.count(num) for num in x}
d.pop(None, None)
But is there a way to do it in one, or to do the dictionary comprehension with an if statement without actually adding any default key for the else statement?
Use Counter to count each items in x, the use a dictionary comprehension to pull those values where the count is greater than or equal to your threshold (e.g. 2).
from collections import Counter
x = [2, 3, 4, 2, 3, 5, 6]
threshold = 2
c = Counter(x)
d = {k: v for k, v in c.iteritems() if v >= threshold}
>>> d
{2: 2, 3: 2}
That works:
{ i: x.count(i) for i in x if x.count(i) >= 2}
The if part must be after the for, not before, that's why you get the syntax error.
To avoid counting elements twice, and without any extra import, you could also use two nested comprehensions (actually the inner one is a generator to avoid iterating the full list twice) :
>>> { j: n for j, n in ((i, x.count(i)) for i in x) if n >= 2}
{2: 2, 3: 2}
The test in your expression: (num if x.count(num) >= 2 else None) comes too late: you already instructed the dict comp to issue a value. You have to filter it out beforehand.
just move the condition from ternary to the filter part of the comprehension:
x = [2,3,4,2,3,5,6]
d = {num: x.count(num) for num in x if x.count(num) >= 2}
that said, this method isn't very effective, because it counts elements twice.
Filter a Counter instead:
import collections
d = {num:count for num,count in collections.Counter(x).items() if count>=2}
This should work:
a = [1,2,2,2,3,4,4,5,6,2,2,2]
{n: a.count(n) for n in set(a) if a.count(n) >= 2}
{2: 6, 4: 2}
This should work:
Input:
a = [2,2,2,2,1,1,1,3,3,4]
Code:
x = { i : a.count(i) for i in a }
print(x)
Output:
>>> {2: 4, 1: 3, 3: 2, 4: 1}

Frequency mapping with dictionary in Python

I am trying to write a function that takes an array and returns a dictonary with keys that denote the unique values in the list and a value that is the count of each item in the list.
def freq(arr):
sum = 0
dict = {}
for i in arr:
if i not in dict:
dict[i] = 1
else:
dict[i] =+ 1
return dict
print(count([1,2,3,4,5,100,100,1000]))
{1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 1000: 1, 100: 1}
I was hoping for
{1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 1000: 1, 100: 2}
collections.Counter already does what you want.
from collections import Counter
c = Counter([1,2,3,4,5,100,100,1000])
print(c)
# Counter({100: 2, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 1000: 1})
So, to reduce the code, and make it more readable, you can just use a default dict instead. To use the default dict, you first have to import it from the collections module and then create the default dict object. The default dictionary requires me to give it something called a factory function. In this case, I'll give it the integer class, and that's essentially going to act as the creator of the default value so that if I try to access a key that doesn't exist, it will create a default value for me using this object as the constructor, and since creating a new int object initializes the value to zero, I can now just access any key, and increment it without checking to see if it's already there.
So you have to import the defaultdict first.
from collections import defaultdict
# your list of numbers
nums = [1,2,3,4,5,100,100,1000]
# use a default dictionary to count each element
numCounter = defaultdict(int)
# Count the elements in the list
for num in nums:
numCounter[num] += 1
# print the result
for (k, v) in numCounter.items():
print(str(k) + ": " + str(v))
The output will be
1:1,
2:1,
3:1,
4:1,
5:1,
100:2,
1000:1

Check for unique values in a dictionary and return a list

I've been struggling with this exercise for a couple of days now, each approximation I find, have a new problem, the idea is to find those unique values on a dictionary, and return a list with the keys
For example:
if aDictionary = {1: 1, 3: 2, 6: 0, 7: 0, 8: 4, 10: 0} then your the function should return [1, 3, 8], as the values 1,2 and 4 only appear once.
This is what I've tried so far:
def existsOnce(aDict):
counting = {}
tempList = []
for k in aDict.keys():
print k,
print aDict[k]
print 'values are:'
for v in aDict.values():
print v,
counting[v] = counting.get(v,0)+1
print counting[v]
tempNumbers = counting[v]
tempList.append(tempNumbers)
print tempList
If I go this way, I can point and delete those that are bigger than one, but the problem persists, I will have one zero, and I don't want it as was not unique in the original list.
def existsOnce2(aDict):
# import Counter module in the top with `from collections import Counter`
c = Counter()
for letter in 'here is a sample of english text':
c[letter] += 1
if c[letter] == 1:
print c[letter],':',letter
I tried to go this way with integers and check which ones appear from first time, but cannot translate it to dictionary or keep going from here. Also I'm not sure if importing modules are allowed in the answer and surely have to be a way to do it without external modules.
def existsOnce3(aDict):
vals = {}
for i in aDict.values():
for j in set(str(i)):
vals[j] = 1+ vals.get(j,0)
print vals
'''till here I get a counter of how many times a value appears in the original dictionary, now I should delete those bigger than 1'''
temp_vals = vals.copy()
for x in vals:
if vals[x] > 1:
print 'delete this: ', 'key:',x,'value:', vals[x]
temp_vals.pop(x)
else:
pass
print 'temporary dictionary values:', temp_vals
'''till here I reduced down the values that appear once, 1, 2 and 4, now I would need the go back and check the original dictionary and return the keys
Original dictionary: {1: 1, 3: 2, 6: 0, 7: 0, 8: 4, 10: 0}
temp_vals {'1': 1, '2': 1, '4': 1}
keys on temp_vals (1,2,4) are the values associated to the keys I got to retrieve from original dictionary (1,3,8)
'''
print '---'
temp_list = []
for eachTempVal in temp_vals:
temp_list.append(eachTempVal)
print 'temporary list values:', temp_list
''' till here I got a temporary list with the values I need to search in aDict'''
print '---'
for eachListVal in temp_list:
print 'eachListVal:', eachListVal
for k,v in aDict.iteritems():
print 'key:',k,'value:',v
From here I cannot take the values for whatever reason and compare them, I've tried to extract the values with statements like:
if v == eachListVal:
do something
But I'm doing something wrong and cannot access to the values.
You just need to use your vals dict and keep keys from aDict with values that have a count == 1 in vals then calling sorted to get a sorted output list:
def existsOnce3(aDict):
vals = {}
# create dict to sum all value counts
for i in aDict.values():
vals.setdefault(i,0)
vals[i] += 1
# use each v/val from aDict as the key to vals
# keeping each k/key from aDict if the count is 1
return sorted(k for k, v in aDict.items() if vals[v] == 1)
Using a collections.Counter dict to do the counting just call Counter on your values then apply the same logic, just keep each k that has a v count == 1 from the Counter dict:
from collections import Counter
cn = Counter(aDict.values())
print(sorted(k for k,v in aDict.items() if cn[v] == 1))
How about this:
from collections import Counter
my_dict = {1: 1, 3: 2, 6: 0, 7: 0, 8: 4, 10: 0}
val_counter = Counter(my_dict.itervalues())
my_list = [k for k, v in my_dict.iteritems() if val_counter[v] == 1]
print my_list
Result:
[1, 3, 8]
One liner:
>>> aDictionary = {1: 1, 3: 2, 6: 0, 7: 0, 8: 4, 10: 0}
>>> unique_values = [k for k,v in aDictionary.items() if list(aDictionary.values()).count(v)==1]
>>> unique_values
[1, 3, 8]

Updating a dictionary by adding the integer 1 to a select few values in a python dictionary [duplicate]

How would you add a constant number, say 1, to a value in a dictionary if certain conditions are fulfilled.
For example, if I had a dictionary:
dict = {'0':3, '1':3, '2':4, '3':4, '4':4}
If I simply wanted to add the integer 1 to every value in the dictionary so it updates dict as this:
dict = {'0':4, '1':4, '2':5, '3':5, '4':5}
When I used the following code where the Cur_FID is the first one in the dictionary '0', it gave me a value of 5? It should have given me 4. ??
for lucodes in gridList2: # a list of the values [3,3,4,4,4] -- have to separate out because it's part of a larger nested list
if lucodes > 1:
if lucodes < 5:
FID_GC_dict[Cur_FID] = lucodes + 1
print FID_GC_dict[Cur_FID] #returned 5??? weird
I want to add 1 to all the values, but stopped here when the first dictionary update did something weird.
One simple way to do this is to use a collections.Counter object, which you can use in every way like a normal dictionary in most ways but it is optimized for keeping a count of items:
>>> from collections import Counter
>>> d = Counter({'0':3, '1':3, '2':4, '3':4, '4':4})
>>> d
Counter({'3': 4, '2': 4, '4': 4, '1': 3, '0': 3})
>>> d.update(d.keys())
>>> d
Counter({'3': 5, '2': 5, '4': 5, '1': 4, '0': 4})
As for only doing it when certain conditions are fulfilled, just use a comprehension or generator to only pass the list of the keys you want to increment to d.update():
>>> d = Counter({'3': 4, '2': 4, '4': 4, '1': 3, '0': 3})
>>> d.update((k for k, v in d.items() if v == 4))
>>> d
Counter({'3': 5, '2': 5, '4': 5, '1': 3, '0': 3})
Another way of doing this would be to use the items() method of dictionary which returns a list of key, value tuples:
def f(dict):
for entry in dict.items():
if entry[1] > 1 and entry[1] < 5:
dict[entry[0]] = entry[1] + 1
return dict
You can then extend this to take an arbitrary function:
def f(dict, func):
for entry in dict.items():
if func(entry[1]):
dict[entry[0]] = entry[1] + 1
return dict
This can be provided a function such as:
def is_greater_than_one(x):
return x > 1
and called in the following way:
f(input_dictionary,is_greater_than_one)
Your code says the following:
for each value in [3,3,4,4,4]:
if 1 < value < 5:
FID_thingy['0'] = value + 1
So it will set FID_thingy['0'] to 4 then 4 then 5 then 5 then 5. Do you see why?

Categories