2014-03-25 55 views
0

我有這個代碼基本上爲csv輸入文件,打印出項目/項目的最低成本和餐館ID。但它在一個輸入文件上拋出「KeyError」,但在另一個輸入文件上完美地工作(兩者都是相同的樣式)。有人能指出它錯在哪裏嗎?由於當使用不同的csv文件作爲輸入時的KeyError

有一些重要事項:: 挑戰::

  1. 我的客戶不想要訪問多個餐館。例如,如果他要求「extreme_fajita,jalapeno_poppers,extra_salsa」,那麼代碼應該打印商店6(它可以作爲組合項目使用),而不是將用戶需求分散在不同的餐館周圍(即使某些餐館提供便宜)。

  2. 其次&最重要的是:假設用戶要求漢堡包。那麼如果某個餐廳'X'給4個漢堡「漢堡」,而另一個餐廳'Y'給予「漢堡+金槍魚+豆腐」如果價格爲3美元,那麼我們會告訴用戶購買餐廳'Y',即使除了用戶要求的'漢堡'外還有其他物品,但只要價格便宜,我們很樂意爲他們提供額外物品。


def build_shops(shop_text): 
    shops = {} 
    for item_info in shop_text: 
     shop_id,cost,items = item_info.replace('\n', '').split(',') 
     cost = float(cost) 
     items = items.split('+') 

     if shop_id not in shops: 
      shops[shop_id] = {} 
     shop_dict = shops[shop_id] 

     for item in items: 
      if item not in shop_dict: 
       shop_dict[item] = [] 
      shop_dict[item].append([cost,items]) 
    return shops 


def solve_one_shop(shop, items): 
    if len(items) == 0: 
     return [0.0, []] 
    all_possible = [] 
    first_item = items[0] 
    for (price,combo) in shop[first_item]: 
     sub_set = [x for x in items if x not in combo] 
     price_sub_set,solution = solve_one_shop(shop, sub_set) 
     solution.append([price,combo]) 
     all_possible.append([price+price_sub_set, solution]) 

    cheapest = min(all_possible, key=(lambda x: x[0])) 
    return cheapest 


def solver(input_data, required_items): 
    shops = build_shops(input_data) 
    print shops 
    result_all_shops = [] 
    for shop_id,shop_info in shops.iteritems(): 
     (price, solution) = solve_one_shop(shop_info, required_items) 
     result_all_shops.append([shop_id, price, solution]) 

    shop_id,total_price,solution = min(result_all_shops, key=(lambda x: x[1])) 
    print('SHOP_ID=%s' % shop_id) 
    sln_str = [','.join(items)+'(%0.2f)'%price for (price,items) in solution] 
    sln_str = '+'.join(sln_str) 
    print(sln_str + ' = %0.2f' % total_price) 



shop_text = open('input.csv','rb')  
#shops = build_shops(shop_text) 
#cheapest=solve_one_shop(shops,items) 
solver(shop_text,['A']) 

input.csv

1,4.00,tuna 
1,8.00,tofu 
2,5.00,tuna 
2,6.50,tofu 
3,4.00,chef_salad 
3,8.00,steak__sandwich 
4,5.00,steak__sandwich 
4,2.50,wine_spritzer 
5,4.00,extreme_fajita 
5,8.00,fancy_eu_water 
6,5.00,fancy_eu_water 
6,6.00,extreme_fajita+jalapeno_poppers+extra_salsa 

但我得到這個錯誤: -

Traceback (most recent call last): 
    File "working.py", line 56, in <module> 
    solver(shop_text,['extra_salsa']) 
    File "working.py", line 42, in solver 
    (price, solution) = solve_one_shop(shop_info, required_items) 
    File "working.py", line 27, in solve_one_shop 
    for (price,combo) in shop[first_item]: 
KeyError: 'extra_salsa' 

而如果我在另一個輸入文件運行它,我得到正確的答案,並不克等任何錯誤。

input.csv

1,2.00,A 
1,1.25,B 
1,2.00,C 
1,1.00,D 
1,1.00,A+B 
1,1.50,A+C 
1,2.50,A+D 
2,3.00,A 
2,1.00,B 
2,1.20,C 
2,1.25,D 

========輸出=========

{'1': {'A': [[2.0, ['A']], [1.0, ['A', 'B']], [1.5, ['A', 'C']], [2.5, ['A', 'D']]], 'C': [[2.0, ['C']], [1.5, ['A', 'C']]], 'B': [[1.25, ['B']], [1.0, ['A', 'B']]], 'D': [[1.0, ['D']], [2.5, ['A', 'D']]]}, '2': {'A': [[3.0, ['A']]], 'C': [[1.2, ['C']]], 'B': [[1.0, ['B']]], 'D': [[1.25, ['D']]]}} 

SHOP_ID=1 
A,B(1.00) = 1.00 

回答

2

會發生什麼地方是沒有extra_salsa在你的店裏?

除了憤怒的薩爾薩愛好客戶,您的腳本不能正常工作,因爲密鑰不存在。

就像你正在檢查是否items是空的,你需要檢查請求的項目實際上是在商店或不:

def solve_one_shop(shop, items): 
    if len(items) == 0: 
     return [0.0, []] 
    all_possible = [] 
    # first_item = items[0] 
    for item in items: 
     price,combo = shop.get(item, (0.0,[])) # This will return 
               # default values when 
               # the key doesn't exist  

讓您通過優化加載代碼開始:

import csv 

from collections import defaultdict 

def build_shops(shop_file_name): 
    shops = defaultdict(list) 
    with open(shop_file_name, 'r') as f: 
     reader = csv.reader(f, delimiter=',') 
     for row in reader: 
      id, cost, items = row 
      cost = float(cost) 
      items = items.split('+') 
      shops[id].append((cost, items,)) 
    return shops 

現在我們有一個返回字典的函數,每個鍵都是代表成本和項目列表的元組列表。

接下來,讓優化求解:

def solver(shops, required_items): 
    result_all_shops = [] 
    shops_with_items = [] 

    for i in required_items: 
     for shop, inventory in shops.iteritems(): 
      for price, items in inventory: 
       if i in items: 
        shops_with_items.append((shop, price, i)) 

    if not shops_with_items: 
     return [] # No shops contained the items 

    for i in required_items: 
     result_all_shops.append(min(filter(lambda x: x[2] == i, shops_with_items), 
               key=lambda x: x[1])) 

    return result_all_shops 

最後,加載了一切:

if __name__ == '__main__': 
    shops = build_shops('input.csv') 
    items = ['extra_salsa','tofu'] 
    result = solver(shops, items) 
    if not result: 
     print('Sorry, no shops contained {}'.format(','.join(items))) 
    else: 
     for shop, item, price in result: 
      print('Shop {} had the item {} for {}'.format(shop,price,item))) 
+0

感謝BURHAN。但extra_salsa在餐廳6。其次,如果我查詢求解器(shop_text,['tuna']),我會得到同樣的錯誤。第三,如果我只用字母替換這些項目(例如,'A'代表'金槍魚','B'代表'豆腐'等),如果我解決了這個問題(shop_text,['A']),我會得到根據需要修正結果。爲什麼在兩個csv文件上這種不同的行爲? – sunita

+0

Burhan Ive編輯我的帖子以包含正確的輸出,以及我的代碼正在工作的文件。請看看並幫我修復它。謝謝 !!!! – sunita

+0

Burkhan,但如果客戶想要:-'extreme_fajita,jalapeno_poppers,extra_salsa',那麼你的代碼給5,6個獨立餐廳。但客戶只希望在一家餐廳(如果可以的話)提供所需的餐點,在這種情況下,餐廳是6.請參閱 - 我編輯了我的帖子並添加了「重要考慮因素」 – sunita

相關問題