Subtract from dict (python) until value is reached - python

I am new to using dict, and would like to subtract from the dict until I have reached a set value. The code for subtraction of a single value from a dict is this:
for k in dict_:
dict_[k] -= 1
Would it be possible to make this code only subtract data from a value in a dict if it is greater than a value that I set (for example 0)?

I think you're looking for something like this
threshold_val = 5 # say
for key, val in my_dict.items():
if val > threshold_val:
my_dict[key] = val - 1 # say we want to decrement by one

That should be pretty easy:
def foo(stop_val, subtraction_limit):
for k in dict_:
if k == stop_val:
break # exit loop
if dict_[k] > subtraction_limit:
dict_[k] -= 1
You should note that you have no control of the order in which the dictionary's keys are being iterated over. It might be different that the order in which you initiated the dictionary.
That means that iteration could stop at any point, and leave some values un-subtracted.

You can try something like this:
#example set value
set_value = 7
for k in d:
if (d[k] > set_value):
d[k] -= 1

Related

I need some help using a dictionary as a function parameter

I need to replicate this same function but instead of having a list as a parameter I need a dictionary. The idea is that the calculation done by the function is done with the values, and the function returns the keys.
def funcion(dic, Sum):
Subset = []
def f(dic, i, Sum):
if i >= len(dic): return 1 if Sum == 0 else 0
count = f(dic, i + 1, Sum)
count += f(dic, i + 1, Sum - dic[i])
return count
for i, x in enumerate(dic):
if f(dic, i + 1, Sum - x) > 0:
Subset.append(x)
Sum -= x
return Subset
The function works if I enter (300, 200,100,400). But i need to use as an input something like {1:300 , 2:200 , 3:100, 4:400 }
So the calculation is done with the values, but it returns the keys that match the condition.
Im trying working with dic.keys() and dic.values() but its not working. Could you help me?
Thank u so much.
Your code isn't working with your dictionary because it's expecting to be able to index into dic with numeric indexes starting at 0 and going up to len(dic)-1. However, you've given your dictionary keys that start at 1 and go to len(dic). That means you need to change things up.
The first change is in the recursive f function, where you need the base case to trigger on i > len(dic) rather than using the >= comparison.
The next change in in the loop that calls f. Rather than using enumerate, which will generate indexes starting at 0 (and pair them with the keys of the dictionary, which is what you get when you directly iterate on it), you probably want to do something else.
Now, ideally, you'd want to iterate on dic.items(), which would give you index, value pairs just like your code expects. But depending on how the dictionary gets built, that might iterate over the values in a different order than you expect. In recent versions of Python, dictionaries maintain the order their keys were added in, so if you're creating the dictionary with {1:300, 2:200, 3:100, 4:400 }, you'll get the right order, but a mostly-equivalent dictionary like {3:100, 4:400, 1:300, 2:200 } would give its results in a different order.
So if you need to be resilient against dictionaries that don't have their keys in the right order, you probably want to directly generate the 1-len(dict) keys yourself with range, and then index to get the x value inside the loop:
for i in range(1, len(dic)+1): # Generate the keys directly from a range
x = dic[i] # and do the indexing manually.
if f(dic, i + 1, Sum - x) > 0: # The rest of the loop is the same as before.
Subset.append(x)
Sum -= x

How to get count of for loop and store it into dictionary which is inside for loop

I am trying to get count of for loop inside each if condition if condition is satisfied it should get the count and store it in a dictionary with diffrent keys example code is given below but it gives me diffrent output not what i want
def get(self, request, format=None):
queryset = preshift.objects.filter(active=True,is_published=True,date_published=self.request.GET.get('date')).values()
data = {}
print('/////queryset_count///',queryset.count())
pre_shift_count = 0
for i in queryset:
dt = i['date_published_local'].strftime("%H")
if int(dt) in range(0,2):
pre_shift_count+=1
print('///1////',pre_shift_count)
data["zero-2"]= pre_shift_count
else:
data["zero-2"] = 0
if int(dt) in range(2,4):
pre_shift_count+=1
print('///2////',pre_shift_count)
data["two-4"] = pre_shift_count
else:
data["two-4"] = 0
if int(dt) in range(4,6):
pre_shift_count+=1
print('///3////',pre_shift_count)
data["two-5"] = pre_shift_count
else:
data["two-5"] = 0
return Response({"preshift":data})
it gives me output like this
('/////queryset_count///',4)
(////1//,1)
(////3//,0)
(////3//,1)
(////3//,2)
(////3//,3)
(////3//,4)
(////3//,5)
i have four records but it's printing 5 i don't have idea of how to get perfect count of for loop inside condition
and i want to store data in dictionary like this
{
"preshift":{
"zero-2":1,
"two-4":0,
"two-5":4,
}
}
I don't have idea of how to get perfect count of for loop inside condition
To get the perfect count of the for loop, I recommend using enumerate() built-in function within Python.Example:
>>> for count, value in enumerate(values):
... print(count, value)
...
0 a
1 b
2 c
This will allow you to keep a perfect count at all times. You can start at count 0 or use +1 to start from 1.
Your desired dictionary is a dictionary within the dictionary. To do this create another dictionary (call b) and use this to assign the values within the forloop. Once all the values are assigned use the other dictionary (call a) and set the key value of preshift in a to b, e.g. a["preshift"] = b. This will make it the way you want.
I am also confused on how you are using the variable pre_shift_count in this case. An easy way around this is to use the b dictionary of type int. You would initialize with defaultdict(int) in python and then in each case increment the value by 1 e.g., b[key]+=1

Python code producing no output. Is the use of generator here correct?

So I recreated the sieve of eratosthenes but the result (prime numbers) is not output as i expected.
The first function is the sieve which returns a dictionary with all integers up to a given range as keys and True or False as their values (prime or not). The generator afterwards is supposed to get all the keys with a value of True (prime numbers). I think the problem is that I haven't used the generator correctly (I just learnt about generators), but I can't spot the mistake.
from math import sqrt
def sieve(x):
values = {}
for l in range(2, x + 1):
values[l] = True
for k in range(2, int(sqrt(x)) + 1):
if values[k] == True:
for j in range(k**2, x + 1, k):
values[j] = False
return values
def primes(dict1):
for l in dict1:
if l == True:
yield list(dict1.keys())[l]
for k in primes(sieve(int(input()))):
print(k, end = " ")
I expect all prime numbers (keys in the dictionary with a value of True) to be printed. But there is no output whatsoever.
Here is the corrected version where you directly access the dictionary keys and values by iterating over them using items(). I have done some changes to the code:
Store the user input in a variable called number
Directly access the keys and the values by iterating over dict1.items()
The point 2 simplifies the expression of yield in your original code.
if l == True: can be simply replaced by if value:
from math import sqrt
def sieve(x):
# function body here
def primes(dict1):
for key, value in dict1.items(): # <--- Directly access keys and values
if value:
yield key
number = int(input())
for k in primes(sieve(number)):
print(k, end = " ")
# 15
# 2 3 5 7 11 13
Iterating over a dictionary with for l in dict1 yields the keys, not the values.
Therefore if l == True is never true.
for l in dict1 iterates over the keys of the dictionary, and the comparison if l==True expects a value. You can fix that, for example, by iterating over both keys and values using items:
for n, isprime in dict1.items():
if isprime:
yield n
A couple of unrelated notes:
you probably want to use a list (or even an array) of Booleans to store sieve data. Using a dict whose keys are consecutive numbers is wasteful.
when testing a Boolean value, use if x rather than if x == True. The latter will give incorrect answer for truthy values other than True, such as 1 or a non-empty container. (To test whether x is false, use if not x.)

Python - Use certain position in list as a condition to trigger something else

I'm trying to think of a way to use a certain index of a list as a condition to trigger something else in python.
For example:
for val in mylist:
do something with val (the actual list entry)
if len(mylist)>= 4 and val has position 2 or bigger in mylist:
do something else
It's important that the if loop remains valid from position 2 until the end of mylist.
what would be a pythonic way to do this?
for i, val in enumerate(my_list):
do_something # will do this always
if i >= 2:
do_also_something_else # will be executed only when index is 2 or greater

A simpler way to run a function on dictionary values w/o losing the association to keys?

I'd like to run a function on all the values in a dictionary. To make things more complicated, the exact transformation each value goes through is not independent, but contingent on the transformations other values before it went through.
Here's a simple function, defined on a list, to show what I mean:
def new_list_generator(mylist):
number_of_iterations = 0
new_list = []
for n in mylist:
if number_of_iterations%2 == 0:
new_list.append(n**1.25)
number_of_iterations += 1
else:
new_list.append(n**0.5)
number_of_iterations += 1
return new_list
You can see that the power we employ on each value depends on the the history - how many values were modified before it.
Now, that's the function defined for a list. What happens when I want to modify a dictionary's values without disassociating keys and values (that is, I don't want to simply create a list of all the values and feed that list to the function)?
The best solution I could think of (and make it work) was the following cumbersome solution:
step 1: transform the dictionary to a list of tuples. i.e. [(value1,key1), (value2,key2),...]
step 2: run a modified function on that list.
step 3: convert the list back to a dictionary with dict().
That is:
some_dict = {"Graham": 13, "Eric": 19, "Terry G": 7, "Terry J":11, "John": 15, "Michael": 7}
dict_to_tuples = some_dict.items()
def new_list_generator1(mylist): # notice it's a new function
number_of_iterations = 0
new_list = []
for n in mylist:
if number_of_iterations%2 == 0:
new_list.append((n[0],n[1]**1.25)) # <== new
number_of_iterations += 1
else:
new_list.append((n[0],n[1]**0.5)) # <== new
number_of_iterations += 1
return new_list
tups = new_list_generator1(dict_to_tuples)
print dict(tups)
I was wondering if there's a less cumbersome way to do that, hopefully without having to modify the original list. I googled around and couldn't find anything informative on Stackoverflow or elsewhere (where the function employed on dict values depends on history).
Thanks for your help.
Just loop through the keys and modify the values directly.
some_dict = {"Graham": 13, "Eric": 19, "Terry G": 7, "Terry J":11, "John": 15, "Michael": 7}
def new_list_generator1(mydict): # notice it's a new function
number_of_iterations = 0
for key in mydict:
if number_of_iterations%2 == 0:
mydict[key] = mydict[key]**1.25
else:
mydict[key] = mydict[key]**0.5
number_of_iterations += 1
return mydict
print new_list_generator1(some_dict)
As #kroolik correctly pointed out below, this can be simplified further with enumerate at least for the current example.
def new_list_generator1(mydict): # notice it's a new function
for i, key in enumerate(mydict):
if i%2 == 0: mydict[key] = mydict[key]**1.25
else: mydict[key] = mydict[key]**0.5
return mydict
As pointed out in the comments, it's quite strange to process values of a dict in terms of the iteration order, because that order is not guaranteed, so it could lead to different values every time you apply the function. That being said, if the only parameter that you take into account when processing is the iteration step, you could simply use a dict comprehension:
{key: some_dict[key]**([1.25, 0.5][i % 2]) for i, key in enumerate(some_dict)}
Or more generally
def process_value(value, iteration_step):
# new_value = ...
return new_value
{key: process_value(some_dict[key], i) for i, key in enumerate(some_dict)}

Categories