2012-04-18 128 views
2

問題查找在CSV文件的特定值的單個列,並返回一整行

代碼不正確地識別輸入(項目)。即使CSV文件中存在這樣的值,它也會轉儲到我的失敗消息。任何人都可以幫助我確定我做錯了什麼?

背景

我工作的一個小程序,用戶輸入查詢(這裏沒有給出功能),在搜索CSV文件(項目)的特定列,並返回整行。 CSV數據格式如下所示。我已經縮短了實際數量的數據(49個字段名稱,18000+行)。

代碼

import csv 
from collections import namedtuple 
from contextlib import closing 

def search(): 
    item = 1000001 
    raw_data = 'active_sanitized.csv' 
    failure = 'No matching item could be found with that item code. Please try again.' 
    check = False 

    with closing(open(raw_data, newline='')) as open_data: 
     read_data = csv.DictReader(open_data, delimiter=';') 
     item_data = namedtuple('item_data', read_data.fieldnames) 
     while check == False: 
      for row in map(item_data._make, read_data): 
       if row.Item == item: 
        return row 
       else: 
        return failure  

CSV結構

active_sanitized.csv 
Item;Name;Cost;Qty;Price;Description 
1000001;Name here:1;1001;1;11;Item description here:1 
1000002;Name here:2;1002;2;22;Item description here:2 
1000003;Name here:3;1003;3;33;Item description here:3 
1000004;Name here:4;1004;4;44;Item description here:4 
1000005;Name here:5;1005;5;55;Item description here:5 
1000006;Name here:6;1006;6;66;Item description here:6 
1000007;Name here:7;1007;7;77;Item description here:7 
1000008;Name here:8;1008;8;88;Item description here:8 
1000009;Name here:9;1009;9;99;Item description here:9 

注意

我與Python的經驗是比較少的,但我認爲這將是開始,以便一個很好的問題了解更多。

我確定了打開CSV文件(並封裝在一個關閉函數中)的方法,通過DictReader讀取數據(以獲取字段名稱),然後創建一個命名的元組,以便能夠快速選擇所需的列輸出(項目,成本,價格,名稱)。列順序很重要,因此使用DictReader和namedtuple。

雖然有可能對每個字段名進行硬編碼,但我覺得如果程序可以在文件打開時讀取它們,當處理具有相同列名的類似文件時,它會更有幫助不同的專欄組織。

研究

+1

您不需要在文件上使用「closing()」 - 它的默認情況下,上下文管理器已經關閉了該文件。只需用''打開(...)作爲文件:''。 – 2012-04-18 12:54:38

+0

'while check == False'是什麼?它永遠是真的...... – 2012-04-18 13:14:21

+0

好的。我在http://docs.python.org/py3k/library/contextlib.html?highlight=closing#contextlib.closing中使用了closing()方法。我在open()文檔中讀到它確實關閉了IO,但是我只是覺得它更安全,然後抱歉,因爲我不確定它們有什麼不同。 – 2012-04-18 13:15:30

回答

2

你有三個問題是:

  • 將返回第一次失敗,所以它永遠不會讓過去的第一道防線。
  • 您正在從文件中讀取字符串,並將其與int進行比較。
  • _make遍歷字典鍵而不是值,產生錯誤的結果(item_data(Item='Name', Name='Price', Cost='Qty', Qty='Item', Price='Cost', Description='Description'))。

    for row in (item_data(**data) for data in read_data): 
        if row.Item == str(item): 
         return row 
    return failure 
    

這修復問題在手 - 我們覈對一個字符串,我們只當沒有一個項目中的匹配(儘管你可能要開始轉換字符串到整數的數據,而不是返回這個字符串/整數問題的修復)。

我也改變了你循環的方式 - 使用生成器表達式使得更自然的語法,使用字典命名屬性的常規構造語法。這比使用_makemap()更清潔並且更具可讀性。它還修復了問題3.

+0

啊好吧。謝謝!我明白我現在的錯誤在哪裏。如果你可以把它寫成一個更自然的語法,那麼爲什麼map()函數存在有一個特別的原因嗎?我使用map()的原因是有很多其他的例子使用它。 – 2012-04-18 13:12:06

+0

有時使用''map()'' - 比如''map(int,list_of_strings)''可以使得列表中的每個元素都成爲''int'',這樣更喜歡''[int (x)for list_of_strings]''因爲你不需要發明變量。一般來說,list,set和dict comps或generator表達式是更好的解決方案。 ''map()''對於習慣於函數式語言的人來說也是一個熟悉的概念。這也是在語言理解之前的宿醉。 – 2012-04-18 13:14:46

+0

我會牢記未來。謝謝您的幫助! – 2012-04-18 13:20:30

相關問題