2016-08-15 23 views
-3

我有一个客户想要一种方法来计算运输成本。它按重量和公里计算(不幸的是不是线性的)。它看起来像这样:Python - 最好的方式来查找类似表格的计划中的值

|   | 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€

什么是这样做的最佳方法?

+1

第一步是尝试自己编写的函数。 – Pureferret

+0

什么是*范围*参数?公里? –

+0

@Pureferret我不想让任何人在这里发布一个函数。这是关于什么是查找这些价值的最佳方式的建议。 – Dominic

回答

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] 
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 

表说:“50公里”,“到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) 
+0

嘿洛朗。感谢您的回答。在我的“真实”函数中,我有一个“舍入”函数,它将值整理到下一个已知断点。 – Dominic

+0

如果你没有问题,你可以投票;-) –

相关问题