3

問題

コードは入力 (項目) を正しく識別しません。そのような値が 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 ファイルを開き (そして close 関数でラップし)、DictReader を介してデータを読み取り (フィールド名を取得するため)、名前付きタプルを作成して、出力に必要な列をすばやく選択できるようにする方法を決定しました (アイテム、コスト、価格、名前)。列の順序は重要であるため、DictReader と namedtuple を使用します。

各フィールド名をハードコーディングする可能性はありますが、ファイルを開いたときにプログラムがそれらを読み取ることができれば、列名は同じで列構成が異なる類似のファイルで作業する場合にはるかに役立つと感じました。

リサーチ

4

1 に答える 1

3

これには 3 つの問題があります。

  • 最初の失敗で戻るため、最初の行を超えることはありません。
  • ファイルから文字列を読み取り、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
    

これにより、当面の問題が修正されます - 文字列に対してチェックし、一致するアイテムがない場合にのみ返されます (ただし、文字列/整数の問題に対するこのハックな修正ではなく、データ内の文字列を int に変換し始めることをお勧めします)。 .

また、ループの方法も変更しました。ジェネレーター式を使用すると、より自然な構文になり、dict の名前付き属性の通常の構築構文が使用されます。_makeこれは、 andを使用するよりもクリーンで読みやすいですmap()。また、問題 3 を修正します。

于 2012-04-18T13:03:10.007 に答える