3

ここにPythonの初心者がいます。おそらく明らかな何かが欠けています。どこでも検索して解決策が見つからなかったので、助けを求めたいと思いました。

大きなcsvファイルからネストされた辞書を作成する関数を作成しようとしています。入力ファイルの形式は次のとおりです。

Product,Price,Cost,Brand,
blue widget,5,4,sony,
red widget,6,5,sony,
green widget,7,5,microsoft,
purple widget,7,6,microsoft,

等...

必要な出力辞書は次のようになります。

projects = { `<Brand>`: { `<Product>`: { 'Price': `<Price>`, 'Cost': `<Cost>` },},}

しかし、明らかに、さまざまな製品を含む多くのさまざまなブランドがあります。入力ファイルでは、データはブランド名のアルファベット順に並べられていますが、DictReaderが実行されるとすぐに並べ替えられなくなることがわかっているので、重複を処理するためのより良い方法が絶対に必要です。書かれているifステートメントは冗長で不要です。

これが私がこれまでに持っている機能しない、役に立たないコードです:

def build_dict(source_file):
  projects = {}
  headers = ['Product', 'Price', 'Cost', 'Brand']
  reader = csv.DictReader(open(source_file), fieldnames = headers, dialect = 'excel')
  current_brand = 'None'
  for row in reader:
    if Brand != current_brand:
      current_brand = Brand
    projects[Brand] = {Product: {'Price': Price, 'Cost': Cost}}
  return projects

source_file = 'merged.csv'
print build_dict(source_file)

もちろん、ファイルの先頭にあるcsvモジュールをインポートしました。

これを行うための最良の方法は何ですか?コースから外れているように感じますが、CSVからネストされたdictを作成するために利用できる情報はほとんどなく、そこにある例は非常に具体的であり、ソリューションが実際に機能する理由について詳しく説明しない傾向があります。 Pythonを初めて使用する人として、結論を出すのは少し難しいです。

また、入力csvファイルには通常ヘッダーがありませんが、この関数の動作バージョンを取得するために、ヘッダー行を手動で挿入しました。理想的には、ヘッダーを割り当てるコードがいくつかあります。

ヘルプ/方向性/推奨事項は大歓迎です、ありがとう!

4

2 に答える 2

6
import csv
from collections import defaultdict

def build_dict(source_file):
    projects = defaultdict(dict)
    headers = ['Product', 'Price', 'Cost', 'Brand']
    with open(source_file, 'rb') as fp:
        reader = csv.DictReader(fp, fieldnames=headers, dialect='excel',
                                skipinitialspace=True)
        for rowdict in reader:
            if None in rowdict:
                del rowdict[None]
            brand = rowdict.pop("Brand")
            product = rowdict.pop("Product")
            projects[brand][product] = rowdict
    return dict(projects)

source_file = 'merged.csv'
print build_dict(source_file)

を生成します

{'microsoft': {'green widget': {'Cost': '5', 'Price': '7'},
               'purple widget': {'Cost': '6', 'Price': '7'}},
 'sony': {'blue widget': {'Cost': '4', 'Price': '5'},
          'red widget': {'Cost': '5', 'Price': '6'}}}

入力データから(merged.csvヘッダーがなく、データのみが含まれる場合)。

ここでは辞書のようなものを使用しdefaultdictましたが、例外を発生させる代わりに存在しないキーを参照すると、デフォルト値(この場合は。)が作成されますdict。それから私は出て-そして削除-BrandそしてProduct、そして残りを保存します。

残っているのは、コストと価格を文字列ではなく数値に変換することだけだと思います。

[DictReaderではなく直接使用するように変更reader]

于 2012-08-31T18:46:31.307 に答える
0

ここで私はあなたの要件を満たす別の方法を提供します(DSMとは異なります)最初に、これは私のコードです:

import csv

new_dict={}
with open('merged.csv','rb')as csv_file:
    data=csv.DictReader(csv_file,delimiter=",")
    for row in data:
        dict_brand=new_dict.get(row['Brand'],dict())
        dict_brand[row['Product']]={k:row[k] for k in ('Cost','Price')}
        new_dict[row['Brand']]=dict_brand
print new_dict

簡単に言えば、解決すべき主なポイントは、要件に含まれるキーと値のペアを把握することです。要件に応じて、 3レベルの辞書と呼ぶことができます。ここで、最初のレベルのキーはBrand元の辞書のintの値であるため、元のcsvファイルから次のように抽出します。

dict_brand=new_dict.get(row['Brand'],dict())

Brandこれは、新しいdictに元のdictと同じ値が存在するかどうかを判断します。存在する場合は挿入し、いいえの場合は作成します。最も複雑な部分は2番目のレベルまたは中間レベルです。ここで設定します。Productキーの新しいdictの値としての元のdictの値Brand、およびの値は、値として元のdictをProduct持つ第3レベルのdictのキーでもあり、ここで次のように抽出します。PriceCost

dict_brand[row['Product']]={k:row[k] for k in ('Cost','Price')}

Brandそして最後に、私たちがする必要があるのは、作成された「中間のdict」を、キーとして持つ新しいdictの値として設定することです。最後に、出力は

{'sony': {'blue widget': {'Price': '5', 'Cost': '4'}, 
'red widget': {'Price': '6', 'Cost': '5'}}, 
'microsoft': {'purple widget': {'Price': '7', 'Cost': '6'}, 
'green widget': {'Price': '7', 'Cost': '5'}}}

それです。

于 2016-09-16T04:29:58.820 に答える