Iterating through arrays with given limits (python) - python

I have measurements from three different elements. (tin, copper, lead)
They get evaluated differently as the have different limits.
For example i have the lead, tin and copper content in a stone mixture as my measurements and the certain limits which return different things.
measurement_lead = 150
measurement_tin = 1
measurement_copper = 1002
limits_lead = [0.5, 10, 50, 100]
limits_tin = [0.7, 14, 990, 11000]
limits_copper = [5, 60, 61, 98880]
Now i have to check if one (or more) of my measurements are above the highest limit, if yes "do something", if no i have to check if one is above the second highest and under the highest limit - and so on, until the condition if the measurement is smaller than the smallest of the limits
Hope it's any clear. Trying to write it in python :)
Edit: There are always 4 limits and the amount can't vary. These are given limits for each element. The measurements can be equal to a limit. It should always check bigger or equal to.
tried this:
measurement_lead = 201
measurement_copper = 10
measurement_tin = 2008
e_mat = 2000
b_mat = 900
pw = 20
t_mat = 1
limits_lead = [t_mat, pw, b_mat, e_mat]
e_mat = 45
b_mat = 43
pw = 34
t_mat = 2
limits_copper = [t_mat, pw, b_mat, e_mat]
e_mat = 10
b_mat = 5
pw = 2
t_mat = 0.5
limits_tin = [t_mat, pw, b_mat, e_mat]
for i in limits_lead:
if i >= e_mat:
print("measurement is higher then e_mat")
elif e_mat >= i >= b_mat:
print("measurement is between e_mat and b_mat")
elif b_mat >= i >= pw:
print("measurement is between b_mat and pw")
elif pw >= i >= t_mat:
print("measurement is between pw and t_mat")
elif t_mat >= i >= rw:
print("measurement is between t_mat and rw")
elif i >= rw:
print("measurement is lower then rw")
Now it somehow needs to check if one measurements is higher the e_mat (with its given limits, every element has different limits), if no: if one measurements is between e_mat and b_mat and so on.

Your question needs some clarification:
Are the limits list always in ascending order? assumption: no
Are there always just 4? assumption: no
What happens if the measurement is equal to a value in your limits? assumption: is never equal
I made some assumptions and wrote a function for you to find out which range your measurement falls in so that you can "do_something":
def find_out_position(limits_element, measurement_element):
limits_element = sorted(limits_element)
limits_element.append(measurement_element)
index = sorted(limits_element).index(measurement_element)
if index == 0:
print ("measurement is lower than lowest")
elif index == len(limits_element)-1:
print ("measurement is higher than highest")
else:
print ("measurement is between {} and {}".format(limits_element[index-1], limits_element[index+1]))

I assumed it doesn't matter if all three measurements meet the limit as long as one does. If that is the case, try this:
if measurement_lead >= limits_lead[3] or measurement_tin >= limits_tin[3] or measurement_copper >= limits_copper[3]:
#do something because 1 or more meets the highest requirement
exit
elif measurement_lead >= limits_lead[2] or measurement_tin >= limits_tin[2] or measurement_copper >= limits_copper[2]:
#do something because 1 or more is between the second highest and highest
exit
elif measurement_lead >= limits_lead[1] or measurement_tin >= limits_tin[1] or measurement_copper >= limits_copper[1]:
#do something because 1 or more is between the third highest and second highest
exit
else:
#do something because 1 or more is between the lowest and third highest
exit
Idk what your do sth is but make sure you end the loop after 'doing something' so that the next elif block only executes if none of the three conditions are met in the previous block. Let me know if that makes sense. :)

Related

Transform the 2d list of poker stacks into list of actions

All poker stacks are scraped every few seconds during one poker hand on the preflop. Here's the list of list of stacks in the big blinds(BB). Player 4 makes mandatory bet 0.5 BB, Player 5 makes 1 BB bet at the start, then players act consecutively from 0 to 5. The first sublist is player 0, the last is player 5.
Return list of actions.
Example 1: [[102,102,102,102]
[101,101,99,99]
[103.5,103.5,103.5]
[100.5,100.5,100.5,93,79.5]
[105.5,105.0,105.0,105.0]
[94,93,93,93,93,73]]
Desired output 1: Fold - Raise 2 - Fold - Raise 7.5 - Fold - Raise 21 - Fold - Call.
Explanation:
Player 0 folded because there's no change in his stack.
Player 1 raised 2 because the stack decreased 101 - 99 = 2 big blinds (BB).
Player 2 folded because there's no change in his stack.
Player 3 raised because the stack decreased 100.5 - 93 = 7.5 big blinds and the decrease is larger than previous bet (2 big blinds).
Player 4 folded because there's no change in his stack after posting small blind (0.5 big blinds or BB).
Player 5 raised 21 because the his overall stack decreased 93 - 73 = 20 big blinds, he also posted 1 big blind so his overall raise size is 20 + 1 = 21).
Player 1 folded because the stack doesn't decrease after his bet.
Player 3 called 21 because his stack decreased 93 - 79.5 = 13.5 BB and his overall bet in the round is 13.5 + 7.5 = 21 BB which equals maximum raise size in current round.
I correctly wrote transform_stacks function that transfroms list of stacks sizes into list of differences, however get_actions function is completely incorrect.
from more_itertools import pairwise
from itertools import zip_longest
 
stacks = [[102,102,102,102], [101,101,99,99], [103.5,103.5,103.5], [100.5,100.5,100.5,93,79.5], [105.5,105.0,105.0,105.0], [94,93,93,93,93,73]]
 
def transform_stacks(stacks): # finds the difference in stack sizes, the functions is normal
u = [[float(x) - float(y) for (x, y) in pairwise(stacks[z]) if x != '' and y != '' and abs(float(y) - float(x)) > 0.499] for z in range(len(stacks))]
#print(u)
#will return [[], [2.0], [], [7.5, 13.5], [0.5], [1.0, 20.0]]
return u
 
transposed = transform_stacks(stacks)
 
def get_actions(stacks):
actions = []
for index in range(len(stacks)):
curr_max = 0
for k in range(len(stacks[index])):
if stacks[index][k] and (stacks[index][k] - 0.01 > curr_max):
actions.append("Raise " + str(stacks[index][k]))
curr_max = stacks[index][k]
elif stacks[index][k]:
actions.append("Call " + str(stacks[index][k]))
 
return actions
print(get_actions(transposed)) # should print ['Fold','Raise 2','Fold','Raise 7.5,'Fold','Raise 21','Fold','Call']
I can't test it right now but try if this works. It might look a bit longer than what you had but I think it's a very intuitive way of going at this problem:
from itertools import accumulate
def get_actions(stacks):
# this part should probably go in the transform_stacks function
# what it does is give you the cumulative total rather than the individual raises
# this makes sense because you want the output to be "raise 21"
# for the BB in the example, rather than "raise 20"
stacks = [list(accumulate(x)) for x in stacks]
SB = None
for i, stack in enumerate(stacks):
try:
if stack[0] == 0.5:
SB = i
break
except IndexError:
continue
# just to make sure
if SB is None:
raise ValueError("Small Blind not found")
num_players = len(stacks)
stacks[SB].pop(0)
bet = stacks[(SB+1)%num_players].pop(0)
action_on_player = (SB+2)%num_players
action_strings, out_of_hand = [], []
while any(stacks):
if action_on_player in out_of_hand:
action_on_player = (action_on_player+1)%num_players
continue
if not stacks[action_on_player]:
action_strings.append("Fold")
out_of_hand.append(action_on_player)
action_on_player = (action_on_player+1)%num_players
continue
action = stacks[action_on_player].pop(0)
if action == bet:
action_strings.append("Call")
else:
action_strings.append("Raise " + str(action))
bet = action
action_on_player = (action_on_player+1)%num_players
return action_strings

Added second value to return and i don't know what's missing in the function's paramater to pass?

Need help with this assignment, python newbie here, 30 minutes till deadline and i couldn't figure out what's missing. my teacher said it won't work like this.
updated,
if 0 < amount <= 20:
return 0.005, 0
if 20 < amount <= 50:
return 0.893, 0
elif 50 <= amount <= 100:
return 1.000, 0
elif 100 <= amount <= 200:
return 1.900, 0
elif 200 <= amount <= 300:
return 2.800, 0
elif 300 <= amount <= 500:
return 3.500, 0
elif 500 <= amount <= 700:
return 4.000, 0
elif 700 <= amount <= 1000:
return 4.750, 0
else:
return 5.500, 0
I think your problem is here
def has_enough_balance(balance, amount, transaction_type):
return balance >= calculate_fee(amount, transaction_type) + amount
calculate_fee() returns a tuple , in your has_enough_balance() function, you add the amount to it, you cant add a numeric and a tuple
index calculate_fee(amount, transaction_type) to choose which variable you want to use there and your code should be fine
"depends on how and where the function should be used later, it's an abstract function "
you could edit your has_enough_balance() function to
def has_enough_balance(balance, amount, transaction_type, fee_type):
index_dict = {"sender":0, "receiver":1}
return balance >= (calculate_fee(amount, transaction_type)[index_dict[fee_type]]) + amount
basically since you have calculate_fee() returning a tuple, you only want to use one of those values at a time.
you can follow the tuple with [*index of the value you want to use*] to grab the correct value. so I added fee_type as a argument for has_enough_balance() and a dictionary inside to let you say whether you want to use your function for the sender fee or the receiver fee, and the dictionary will match it to its corresponding index, and [index_dict[fee_type]] grabs the correct slice out of calculate_fee()
Your calculate_fee method returns two variables.
In python, when you return multiple variables that's a tuple (example: (0, 0))
But in this block of code
# Checking if client has enough balance before request is sent
def has_enough_balance(balance, amount, transaction_type):
return balance >= calculate_fee(amount, transaction_type) + amount
You try to compare it to a single variable balance and you also try to add it to a single variable amount. These operations are not supported between a tuple, and an int.
From your comment i saw that calculate_fee returns the fee for the sender and the fee for the receiver.
You could edit your has_enough_balance function with a boolean parameter forSender to know if you're calculating the amount for the sender or for the receiver.
You could then use the value of this parameter to know which of the two fees you need to add in your calculation.
# Checking if client has enough balance before request is sent
def has_enough_balance(balance, amount, transaction_type, forSender):
senderFee, receiverFee = calculate_fee(amount, transaction_type)
fee = senderfEE if forSender else receiverFee
return balance >= fee + amount

How to properly add gradually increasing/decreasing space between objects?

I've trying to implement transition from an amount of space to another which is similar to acceleration and deceleration, except i failed and the only thing that i got from this was this infinite stack of mess, here is a screenshot showing this in action:
you can see a very black circle here, which are in reality something like 100 or 200 circles stacked on top of each other
and i reached this result using this piece of code:
def Place_circles(curve, circle_space, cs, draw=True, screen=None):
curve_acceleration = []
if type(curve) == tuple:
curve_acceleration = curve[1][0]
curve_intensity = curve[1][1]
curve = curve[0]
#print(curve_intensity)
#print(curve_acceleration)
Circle_list = []
idx = [0,0]
for c in reversed(range(0,len(curve))):
for p in reversed(range(0,len(curve[c]))):
user_dist = circle_space[curve_intensity[c]] + curve_acceleration[c] * p
dist = math.sqrt(math.pow(curve[c][p][0] - curve[idx[0]][idx[1]][0],2)+math.pow(curve [c][p][1] - curve[idx[0]][idx[1]][1],2))
if dist > user_dist:
idx = [c,p]
Circle_list.append(circles.circles(round(curve[c][p][0]), round(curve[c][p][1]), cs, draw, screen))
This place circles depending on the intensity (a number between 0 and 2, random) of the current curve, which equal to an amount of space (let's say between 20 and 30 here, 20 being index 0, 30 being index 2 and a number between these 2 being index 1).
This create the stack you see above and isn't what i want, i also came to the conclusion that i cannot use acceleration since the amount of time to move between 2 points depend on the amount of circles i need to click on, knowing that there are multiple circles between each points, but not being able to determine how many lead to me being unable to the the classic acceleration formula.
So I'm running out of options here and ideas on how to transition from an amount of space to another.
any idea?
PS: i scrapped the idea above and switched back to my master branch but the code for this is still available in the branch i created here https://github.com/Mrcubix/Osu-StreamGenerator/tree/acceleration .
So now I'm back with my normal code that don't possess acceleration or deceleration.
TL:DR i can't use acceleration since i don't know the amount of circles that are going to be placed between the 2 points and make the time of travel vary (i need for exemple to click circles at 180 bpm of one circle every 0.333s) so I'm looking for another way to generate gradually changing space.
First, i took my function that was generating the intensity for each curves in [0 ; 2]
Then i scrapped the acceleration formula as it's unusable.
Now i'm using a basic algorithm to determine the maximum amount of circles i can place on a curve.
Now the way my script work is the following:
i first generate a stream (multiple circles that need to be clicked at high bpm)
this way i obtain the length of each curves (or segments) of the polyline.
i generate an intensity for each curve using the following function:
def generate_intensity(Circle_list: list = None, circle_space: int = None, Args: list = None):
curve_intensity = []
if not Args or Args[0] == "NewProfile":
prompt = True
while prompt:
max_duration_intensity = input("Choose the maximum amount of curve the change in intensity will occur for: ")
if max_duration_intensity.isdigit():
max_duration_intensity = int(max_duration_intensity)
prompt = False
prompt = True
while prompt:
intensity_change_odds = input("Choose the odds of occurence for changes in intensity (1-100): ")
if intensity_change_odds.isdigit():
intensity_change_odds = int(intensity_change_odds)
if 0 < intensity_change_odds <= 100:
prompt = False
prompt = True
while prompt:
min_intensity = input("Choose the lowest amount of spacing a circle will have: ")
if min_intensity.isdigit():
min_intensity = float(min_intensity)
if min_intensity < circle_space:
prompt = False
prompt = True
while prompt:
max_intensity = input("Choose the highest amount of spacing a circle will have: ")
if max_intensity.isdigit():
max_intensity = float(max_intensity)
if max_intensity > circle_space:
prompt = False
prompt = True
if Args:
if Args[0] == "NewProfile":
return [max_duration_intensity, intensity_change_odds, min_intensity, max_intensity]
elif Args[0] == "GenMap":
max_duration_intensity = Args[1]
intensity_change_odds = Args[2]
min_intensity = Args[3]
max_intensity = Args[4]
circle_space = ([min_intensity, circle_space, max_intensity] if not Args else [Args[0][3],circle_space,Args[0][4]])
count = 0
for idx, i in enumerate(Circle_list):
if idx == len(Circle_list) - 1:
if random.randint(0,100) < intensity_change_odds:
if random.randint(0,100) > 50:
curve_intensity.append(2)
else:
curve_intensity.append(0)
else:
curve_intensity.append(1)
if random.randint(0,100) < intensity_change_odds:
if random.randint(0,100) > 50:
curve_intensity.append(2)
count += 1
else:
curve_intensity.append(0)
count += 1
else:
if curve_intensity:
if curve_intensity[-1] == 2 and not count+1 > max_duration_intensity:
curve_intensity.append(2)
count += 1
continue
elif curve_intensity[-1] == 0 and not count+1 > max_duration_intensity:
curve_intensity.append(0)
count += 1
continue
elif count+1 > 2:
curve_intensity.append(1)
count = 0
continue
else:
curve_intensity.append(1)
else:
curve_intensity.append(1)
curve_intensity.reverse()
if curve_intensity.count(curve_intensity[0]) == len(curve_intensity):
print("Intensity didn't change")
return circle_space[1]
print("\n")
return [circle_space, curve_intensity]
with this, i obtain 2 list, one with the spacing i specified, and the second one is the list of randomly generated intensity.
from there i call another function taking into argument the polyline, the previously specified spacings and the generated intensity:
def acceleration_algorithm(polyline, circle_space, curve_intensity):
new_circle_spacing = []
for idx in range(len(polyline)): #repeat 4 times
spacing = []
Length = 0
best_spacing = 0
for p_idx in range(len(polyline[idx])-1): #repeat 1000 times / p_idx in [0 ; 1000]
# Create multiple list containing spacing going from circle_space[curve_intensity[idx-1]] to circle_space[curve_intensity[idx]]
spacing.append(np.linspace(circle_space[curve_intensity[idx]],circle_space[curve_intensity[idx+1]], p_idx).tolist())
# Sum distance to find length of curve
Length += abs(math.sqrt((polyline[idx][p_idx+1][0] - polyline[idx][p_idx][0]) ** 2 + (polyline [idx][p_idx+1][1] - polyline[idx][p_idx][1]) ** 2))
for s in range(len(spacing)): # probably has 1000 list in 1 list
length_left = Length # Make sure to reset length for each iteration
for dist in spacing[s]: # substract the specified int in spacing[s]
length_left -= dist
if length_left > 0:
best_spacing = s
else: # Since length < 0, use previous working index (best_spacing), could also jsut do `s-1`
if spacing[best_spacing] == []:
new_circle_spacing.append([circle_space[1]])
continue
new_circle_spacing.append(spacing[best_spacing])
break
return new_circle_spacing
with this, i obtain a list with the space between each circles that are going to be placed,
from there, i can Call Place_circles() again, and obtain the new stream:
def Place_circles(polyline, circle_space, cs, DoDrawCircle=True, surface=None):
Circle_list = []
curve = []
next_circle_space = None
dist = 0
for c in reversed(range(0, len(polyline))):
curve = []
if type(circle_space) == list:
iter_circle_space = iter(circle_space[c])
next_circle_space = next(iter_circle_space, circle_space[c][-1])
for p in reversed(range(len(polyline[c])-1)):
dist += math.sqrt((polyline[c][p+1][0] - polyline[c][p][0]) ** 2 + (polyline [c][p+1][1] - polyline[c][p][1]) ** 2)
if dist > (circle_space if type(circle_space) == int else next_circle_space):
dist = 0
curve.append(circles.circles(round(polyline[c][p][0]), round(polyline[c][p][1]), cs, DoDrawCircle, surface))
if type(circle_space) == list:
next_circle_space = next(iter_circle_space, circle_space[c][-1])
Circle_list.append(curve)
return Circle_list
the result is a stream with varying space between circles (so accelerating or decelerating), the only issue left to be fixed is pygame not updating the screen with the new set of circle after i call Place_circles(), but that's an issue i'm either going to try to fix myself or ask in another post
the final code for this feature can be found on my repo : https://github.com/Mrcubix/Osu-StreamGenerator/tree/Acceleration_v02

Python Filtering a Point Cloud with PhotoScan Based on a Threshold Value - basic python help needed

I'm trying to implement a filter with Python to sort out the points on a point cloud generated by Agisoft PhotoScan. PhotoScan is a photogrammetry software developed to be user friendly but also allows to use Python commands through an API.
Bellow is my code so far and I'm pretty sure there is better way to write it as I'm missing something. The code runs inside PhotoScan.
Objective:
Selecting and removing 10% of points at a time with error within defined range of 50 to 10. Also removing any points within error range less than 10% of the total, when the initial steps of selecting and removing 10% at a time are done. Immediately after every point removal an optimization procedure should be done. It should stop when no points are selectable or when selectable points counts as less than 1% of the present total points and it is not worth removing them.
Draw it for better understanding:
Actual Code Under Construction (3 updates - see bellow for details):
import PhotoScan as PS
import math
doc = PS.app.document
chunk = doc.chunk
# using float with range and that by setting i = 1 it steps 0.1 at a time
def precrange(a, b, i):
if a < b:
p = 10**i
sr = a*p
er = (b*p) + 1
p = float(p)
for n in range(sr, er):
x = n/p
yield x
else:
p = 10**i
sr = b*p
er = (a*p) + 1
p = float(p)
for n in range(sr, er):
x = n/p
yield x
"""
Determine if x is close to y:
x relates to nselected variable
y to p10 variable
math.isclose() Return True if the values a and b are close to each other and
False otherwise
var is the tolerance here setted as a relative tolerance:
rel_tol is the relative tolerance – it is the maximum allowed difference
between a and b, relative to the larger absolute value of a or b. For example,
to set a tolerance of 5%, pass rel_tol=0.05. The default tolerance is 1e-09,
which assures that the two values are the same within about 9 decimal digits.
rel_tol must be greater than zero.
"""
def test_isclose(x, y, var):
if math.isclose(x, y, rel_tol=var): # if variables are close return True
return True
else:
False
# 1. define filter limits
f_ReconstUncert = precrange(50, 10, 1)
# 2. count initial point number
tiePoints_0 = len(chunk.point_cloud.points) # storing info for later
# 3. call Filter() and init it
f = PS.PointCloud.Filter()
f.init(chunk, criterion=PS.PointCloud.Filter.ReconstructionUncertainty)
a = 0
"""
Way to restart for loop!
should_restart = True
while should_restart:
should_restart = False
for i in xrange(10):
print i
if i == 5:
should_restart = True
break
"""
restartLoop = True
while restartLoop:
restartLoop = False
for count, i in enumerate(f_ReconstUncert): # for each threshold value
# count points for every i
tiePoints = len(chunk.point_cloud.points)
p10 = int(round((10 / 100) * tiePoints, 0)) # 10% of the total
f.selectPoints(i) # selects points
nselected = len([p for p in chunk.point_cloud.points if p.selected])
percent = round(nselected * 100 / tiePoints, 2)
if nselected == 0:
print("For threshold {} there´s no selectable points".format(i))
break
elif test_isclose(nselected, p10, 0.1):
a += 1
print("Threshold found in iteration: ", count)
print("----------------------------------------------")
print("# {} Removing points from cloud ".format(a))
print("----------------------------------------------")
print("# {}. Reconstruction Uncerntainty:"
" {:.2f}".format(a, i))
print("{} - {}"
" ({:.1f} %)\n".format(tiePoints,
nselected, percent))
f.removePoints(i) # removes points
# optimization procedure needed to refine cameras positions
print("--------------Optimizing cameras-------------\n")
chunk.optimizeCameras(fit_f=True, fit_cx=True,
fit_cy=True, fit_b1=False,
fit_b2=False, fit_k1=True,
fit_k2=True, fit_k3=True,
fit_k4=False, fit_p1=True,
fit_p2=True, fit_p3=False,
fit_p4=False, adaptive_fitting=False)
# count again number of points in point cloud
tiePoints = len(chunk.point_cloud.points)
print("= {} remaining points after"
" {} removal".format(tiePoints, a))
# reassigning variable to get new 10% of remaining points
p10 = int(round((10 / 100) * tiePoints, 0))
percent = round(nselected * 100 / tiePoints, 2)
print("----------------------------------------------\n\n")
# restart loop to investigate from range start
restartLoop = True
break
else:
f.resetSelection()
continue # continue to next i
else:
f.resetSelection()
print("for loop didnt work out")
print("{} iterations done!".format(count))
tiePoints = len(chunk.point_cloud.points)
print("Tiepoints 0: ", tiePoints_0)
print("Tiepoints 1: ", tiePoints)
Problems:
A. Currently I'm stuck on an endless processing because of a loop. I know it's about my bad coding. But how do I implement my objective and get away with the infinite loops? ANSWER: Got the code less confusing and updated above.
B. How do I start over (or restart) my search for valid threshold values in the range(50, 20) after finding one of them? ANSWER: Stack Exchange: how to restart a for loop
C. How do I turn the code more pythonic?
IMPORTANT UPDATE 1: altered above
Using a better range with float solution adapted from stackoverflow: how-to-use-a-decimal-range-step-value
# using float with range and that by setting i = 1 it steps 0.1 at a time
def precrange(a, b, i):
if a < b:
p = 10**i
sr = a*p
er = (b*p) + 1
p = float(p)
return map(lambda x: x/p, range(sr, er))
else:
p = 10**i
sr = b*p
er = (a*p) + 1
p = float(p)
return map(lambda x: x/p, range(sr, er))
# some code
f_ReconstUncert = precrange(50, 20, 1)
And also using math.isclose() to determine if selected points are close to the 10% selected points instead of using a manual solution through assigning new variables. This was implemented as follows:
"""
Determine if x is close to y:
x relates to nselected variable
y to p10 variable
math.isclose() Return True if the values a and b are close to each other and
False otherwise
var is the tolerance here setted as a relative tolerance:
rel_tol is the relative tolerance – it is the maximum allowed difference
between a and b, relative to the larger absolute value of a or b. For example,
to set a tolerance of 5%, pass rel_tol=0.05. The default tolerance is 1e-09,
which assures that the two values are the same within about 9 decimal digits.
rel_tol must be greater than zero.
"""
def test_threshold(x, y, var):
if math.isclose(x, y, rel_tol=var): # if variables are close return True
return True
else:
False
# some code
if test_threshold(nselected, p10, 0.1):
# if true then a valid threshold is found
# some code
UPDATE 2: altered on code under construction
Minor fixes and got to restart de for loop from beginning by following guidance from another Stack Exchange post on the subject. Have to improve the range now or alter the isclose() to get more values.
restartLoop = True
while restartLoop:
restartLoop = False
for i in range(0, 10):
if condition:
restartLoop = True
break
UPDATE 3: Code structure to achieve listed objectives:
threshold = range(0, 11, 1)
listx = []
for i in threshold:
listx.append(i)
restart = 0
restartLoop = True
while restartLoop:
restartLoop = False
for idx, i in enumerate(listx):
print("do something as printing i:", i)
if i > 5: # if this condition restart loop
print("found value for condition: ", i)
del listx[idx]
restartLoop = True
print("RESTARTING LOOP\n")
restart += 1
break # break inner while and restart for loop
else:
# continue if the inner loop wasn't broken
continue
else:
continue
print("restart - outer while", restart)

Bijective relations between ranges and some constants?

Please, move this question to Code Review -area. It is better suited there because I know the code below is junk and I wanted critical feedback to complete rewrite.
How can I write the set-to-constants relations in Python? So if A in a range, then return its corresponding constant.
[0,10] <-> a
]10,77] <-> b
]77,\inf[ <-> c
Smelling code, bad.
# Bad style
provSum=0
# TRIAL 1: messy if-clauses
for sold in getSelling():
if (sold >=0 & sold <7700):
rate =0.1
else if (sold>=7700 & sold <7700):
#won't even correct mistakes here because it shows how not to do things
rate =0.15
else if (sold>=7700):
rate =0.20
# TRIAL 2: messy, broke it because it is getting too hard to read
provisions= {"0|2000":0.1, "2000|7700":0.15, "7700|99999999999999":0.20}
if int(sold) >= int(border.split("|")[0]) & int(sold) < int(border.split("|")[1]):
print sold, rate
provSum = provSum + sold*rate
If the list was longer than a mere three entries, I would use bisect.bisect():
limits = [0, 2000, 7700]
rates = [0.1, 0.15, 0.2]
index = bisect.bisect(limits, sold) - 1
if index >= 0:
rate = rates[index]
else:
# sold is negative
But this seems a bit overengineered for just three values...
Edit: On second thought, the most readable variant probably is
if sold >= 7700:
rate = 0.2
elif sold >= 2000:
rate = 0.15
elif sold >= 0:
rate = 0.1
else:
# sold is negative
if (sold >=0 & sold <7700):
is equivalent to
if 0 <= sold < 7700:
I'm not aware of a really great way to map ranges but this makes it much nicer looking at least.
You could use your 2nd approach too:
provisions = {(0, 2000) : 0.1, (2000,7700):0.15, (7700, float("inf")):0.20}
# loop though the items and find the first that's in range
for (lower, upper), rate in provisions.iteritems():
if lower <= sold < upper:
break # `rate` remains set after the loop ..
# which pretty similar (see comments) to
rate = next(rate for (lower, upper), rate in
provisions.iteritems() if lower <= sold < upper)

Categories