我有一个问题,在纸上很简单,但我很难在代码中解决问题。在进一步讨论之前,这不是字符串拆分问题。
我有一个基本上是带状时间表的应用程序。比例是根据客户变化的,但一个例子是一个月的前三个小时是80,接下来的三个小时是70,其余的是50.我目前在代码中代表这个:
scale = [80, 80, 80, 70, 70, 70, 50]
......但我也对那里的建议持开放态度。
步骤的规模和数量是 - 并且必须是可变的。我的一些账单对某些客户来说要简单得多,但我希望能够提供这种高使用率的计划。
但是我如何花费数小时工作(例如15.2)并计算他们应该支付多少钱?如何将这个大数字分成乐队?正如我所说的那样,在纸上工作很容易,但随着我获得更多客户和更复杂的计划,这变得非常无聊。以下是我将如何处理15.2小时:
3 hours at 80 = 240
3 hours at 70 = 210
9.2 hours at 50 = 460
total = 910
虽然我很喜欢,但我很欣赏有关我想要描述的正确名称的评论。而Oli,如果你在2023年回到这里,下次选择一个更容易的计费方案,伙计。
答案 0 :(得分:2)
如果我在这里正确理解问题,那就是我的尝试。它不紧凑,但我更喜欢可读。我将波段表示更改为[(hours, price), (hours, price), ... (None, Price)]
,请参见下面的示例:
def calculate_cost(hours, bands):
remaining_hours = hours
current_band_idx = 0
total_cost = 0
while remaining_hours > 0:
band_max_hours, band_cost = bands[current_band_idx]
if band_max_hours is None:
band_billable_hours = remaining_hours
else:
band_billable_hours = min(remaining_hours, band_max_hours)
total_cost += band_billable_hours * band_cost
current_band_idx += 1
remaining_hours -= band_billable_hours
return total_cost
以你的例子为例:
>>> calculate_cost(15.2, [(3, 80), (3, 70), (None, 50)])
910.0
答案 1 :(得分:2)
首先,我会转过身来:
scale = [80, 80, 80, 70, 70, 70, 50]
进入这个:
import math
scale = {(0, 3): 80, (3, 6): 70, (6, math.inf): 50}
然后我的算法的其余部分如下:
# Total hours worked
hours_worked = 15.2
# Handle the decimal (if any) to begin with... First find the "max" rate
decimal_rate = next(rate for (lower, upper), rate in scale.items()
if lower <= hours_worked and upper >= hours_worked)
# Then calculate the last "sliver" of pay
decimal_end = hours_worked - int(hours_worked)
end_pay = decimal_end * decimal_rate
# Use an integer for ease of calculation
hours_worked = int(hours_worked)
hours_paid_for = 0
# Beginning total pay is just the decimal "ending"
total_pay = end_pay
while hours_paid_for < hours_worked:
# Find the rate for the current bucket of hours
rate_filter = (rate for (lower, upper), rate in scale.items() if lower <= hours_paid_for and hours_paid_for < upper)
current_level = next(rate_filter)
print('Hour: {}'.format(hours_paid_for))
print('Pay rate: ${}'.format(current_level))
total_pay += current_level
hours_paid_for += 1
print('Total earned: ${}'.format(total_pay))
输出如下:
Hour: 0
Pay rate: $80
Hour: 1
Pay rate: $80
Hour: 2
Pay rate: $80
Hour: 3
Pay rate: $70
Hour: 4
Pay rate: $70
Hour: 5
Pay rate: $70
Hour: 6
Pay rate: $50
Hour: 7
Pay rate: $50
Hour: 8
Pay rate: $50
Hour: 9
Pay rate: $50
Hour: 10
Pay rate: $50
Hour: 11
Pay rate: $50
Hour: 12
Pay rate: $50
Hour: 13
Pay rate: $50
Hour: 14
Pay rate: $50
Total earned: $910.0
这里也是一个很好的功能:
def calculate_pay(scale, hours_worked):
# Handle the decimal (if any) to begin with... First find the "max" rate
decimal_rate = next(rate for (lower, upper), rate in scale.items()
if lower <= hours_worked and upper >= hours_worked)
# Then calculate the last "sliver" of pay
decimal_end = hours_worked - int(hours_worked)
end_pay = decimal_end * decimal_rate
# Use an integer for ease of calculation
hours_worked = int(hours_worked)
# Hours already paid for (int)
hours_paid_for = 0
# Beginning 'total pay' can be the decimal end, if any
total_pay = end_pay
while hours_paid_for < hours_worked:
# Find the rate for the current bucket of hours
rate_filter = (rate for (lower, upper), rate in scale.items()
if lower <= hours_paid_for and hours_paid_for < upper)
current_level = next(rate_filter)
total_pay += current_level
hours_paid_for += 1
return total_pay
答案 2 :(得分:1)
虽然在我的评论中我建议采用最简单/最天真的方法并且只是循环 - 我的好奇心让我变得更好,所以这里是使用递归的“少线”方法。
从一个“成本桶”列表开始,每个成本桶包含一定数量小时的价格(例如,[3,80] => 3小时,价格为80个单位),您可以将您的小时数分解为您已按顺序填充每个桶(或已到达最后一个桶,其中所有剩余时间都“花费”)。
# each bucket is a pair of [max hours at this rate, rate per hour]
def calc_cost(cost_buckets: list, hours_worked):
if hours_worked <= cost_buckets[0][0] or len(cost_buckets) < 2:
return cost_buckets[0][1] * hours_worked
return calc_cost(cost_buckets, cost_buckets[0][0]) + calc_cost(cost_buckets[1:], hours_worked - cost_buckets[0][0])
hours = 2.5 # number of hours total worked
costs = [[1,12], [5,30]] # list of 'cost buckets'
print(calc_cost(costs, hours)) # prints '57.0'
这是一种不灵活的方法,但它会完全按照你的具体做法。
(我应该明确指出递归的常见问题;因为如果你想要有一个100,000工时计划,有20,000个成本桶 - 你可能不想这样做。)
答案 3 :(得分:0)
这是另一种方法,使用您首先使用的速率存储方案。 此方法假定项目的工作小时数至少与s
中的费率数量相同(即len(s)
)!
# Original rate scaling method
s = [80, 80, 80, 70, 70, 70, 50]
hours_worked = 15.2
final_hours_rate = s[-1]
# Handle the "decimal end"
end_pay = (hours_worked - int(hours_worked)) * final_hours_rate
hours_worked = int(hours_worked)
n_rates = len(s)
remainder = sum(s[hour] for hour in range(n_rates)) + \
final_hours_rate * (hours_worked - n_rates)
total_pay = end_pay + remainder
total_pay
是910。