我有一位客户想要一种计算运费的方法。它是按重量和公里计算的(不幸的是不是线性的)。它看起来像这样:
| | To 50km | To 100km | To 150km | To 200km |
|------- |--------- |---------- |---------- |---------- |
| 10kg | 84€ | 95€ | 104.45€ | 116€ |
| 20kg | 98€ | 108.50€ | 117.10€ | 127.20€ |
| 30kg | 112.40€ | 121.20€ | 129.95€ | 149.30€ |
我想通过调用类似calc_shipping_costs(range, weight)
的函数来查找值,例如calc_shipping_costs(100, 20)
,然后接收 108.50€
这样做的最佳方法是什么?
答案 0 :(得分:0)
所以如果有人想知道的话。我是这样做的:
def calc_shipping_cost(weight, kilometer):
WEIGHT_BREAKPOINTS = [10, 20, 40, 60, 80, 100, 500]
KILOMETER_BREAKPOINTS = [50, 100, 150, 200, 999]
prices = [
[84.85, 95.15, 104.45, 116.70, 122.25],
[98.65, 108.45, 117.20, 127.95, 134.60],
[112.40, 121.70, 129.95, 149.30, 153.10],
[139.95, 148.20, 155.45, 173.10, 177.80],
[153.70, 167.50, 168.20, 193.20, 196.30],
[181.25, 188.00, 193.70, 225.85, 227.15],
[208.80, 214.50, 219.20, 281.00, 282.70],
]
row = WEIGHT_BREAKPOINTS.index(weight)
col = KILOMETER_BREAKPOINTS.index(kilometer)
return prices[row][col]
答案 1 :(得分:0)
我同意这个问题可以被视为偏离主题,但是,这一次,这是一个现实世界的问题需要解决,而不是学生的问题。
不幸的是,您提供的解决方案是错误的:您只考虑可以拥有“断点”值。如果您给出不同的权重(例如21)或公里(例如55),则该函数会引发异常:
>>> calc_shipping_cost(20, 50)
98.65
>>> calc_shipping_cost(21, 55)
Traceback (most recent call last):
File "python", line 1, in <module>
File "python", line 16, in calc_shipping_cost
ValueError: 21 is not in list
表格显示“To 50km”,“To 100km”等。所以你需要一个更宽容的功能并考虑间隔:例如:[0,50 [,[50,100 [等等]
要在有序的间隔列表中选择值的索引,可以考虑数组二分算法。 Python在bisect模块中有效地实现了该算法。它通常用于计算有序数组中项的插入点。
例如:
>>> import bisect
>>> WEIGHT_BREAKPOINTS = [10, 20, 40, 60, 80, 100, 500]
>>> bisect.bisect_left(WEIGHT_BREAKPOINTS, 10)
0
>>> bisect.bisect_left(WEIGHT_BREAKPOINTS, 40)
2
>>> bisect.bisect_left(WEIGHT_BREAKPOINTS, 25)
2
对于最后一个例子,插入点25是索引2(在40之前插入,索引也是2)。
如果“超出范围”,您可以提出自己的例外或只是ValueError
。
这是一个更好的实现:
import bisect
def calc_shipping_cost(weight, kilometer):
WEIGHT_BREAKPOINTS = [10, 20, 40, 60, 80, 100, 500]
KILOMETER_BREAKPOINTS = [50, 100, 150, 200, 999]
prices = [
[84.85, 95.15, 104.45, 116.70, 122.25],
[98.65, 108.45, 117.20, 127.95, 134.60],
[112.40, 121.70, 129.95, 149.30, 153.10],
[139.95, 148.20, 155.45, 173.10, 177.80],
[153.70, 167.50, 168.20, 193.20, 196.30],
[181.25, 188.00, 193.70, 225.85, 227.15],
[208.80, 214.50, 219.20, 281.00, 282.70],
]
row = bisect.bisect_left(WEIGHT_BREAKPOINTS, weight)
col = bisect.bisect_left(KILOMETER_BREAKPOINTS, kilometer)
try:
return prices[row][col]
except IndexError:
raise ValueError(weight, kilometer)
具有以下行为:
>>> calc_shipping_cost(10, 50)
84.85
>>> calc_shipping_cost(10.0, 50)
84.85
>>> calc_shipping_cost(20, 50)
98.65
>>> calc_shipping_cost(21, 55)
121.7
>>> calc_shipping_cost(10.0, 50)
84.85
>>> calc_shipping_cost(500, 50)
208.8
>>> calc_shipping_cost(1000, 50)
Traceback (most recent call last):
File "python", line 1, in <module>
File "python", line 24, in calc_shipping_cost
ValueError: (1000, 50)