1

在庫を調べて、それをすべての可能な在庫アイテムのマスター リストと比較し、不足しているアイテムを教えてくれるスクリプトを書いています。私の目標は、最初の列に一意のキー整数が含まれ、残りのいくつかの列にそのキーに関連するデータが含まれる .csv ファイルです。たとえば、最終目標の .csv ファイルの 3 行のスニペットは次のようになります。

100001,apple,fruit,medium,12,red
100002,carrot,vegetable,medium,10,orange
100005,radish,vegetable,small,10,red

このためのデータは、いくつかの情報源から引き出されています。1 つ目は、API サーバーにクエリを実行すると、インベントリにあるアイテムのキーのリストが表示されます。2番目に、.csvファイルを、可能なすべてのキーのアイテム名とキーを一致させる辞書に読み込みます。この .csv ファイルの最初の 5 行のスニペットは、次のようになります。

100001,apple
100002,carrot
100003,pear
100004,banana
100005,radish

この 2 列の .csv ファイルには、すべてのキーとそれに対応するアイテム名が記載されており、このリストから手持ちの在庫を差し引いたものが、探しているもの (これが必要な在庫) になります。取得するため)。

これまでのところ、インベントリにないアイテムのキーとアイテム名だけを含む .csv ファイルを取得できます。次のように手元にある在庫のリストを指定します。

100003,100004

結果の .csv ファイルのスニペットは次のようになります。

100001,apple
100002,carrot
100005,radish

これは、ナシとバナナが在庫にあることを意味します (したがって、これらはこの .csv ファイルにはありません)。

これを取得するために、次のようなアイテム ID が指定されたときにアイテム名を取得する関数があります。

def getNames(id_to_name, ids):
    return [id_to_name[id] for id in ids]

次に、リストを返す在庫サーバー API 呼び出しからキーのリストを整数として与える関数を次のように実行しました。

invlist = ServerApiCallFunction(AppropriateInfo)

3 番目の関数は、この invlist を入力として受け取り、持っていないアイテムのキー (アイテム ID) と名前の辞書を返します。また、この dict の情報を .csv ファイルに書き込みます。これを行うには set1 - set2 メソッドを使用しています。次のようになります。

def InventoryNumbers(inventory):
    with open(csvfile,'w') as c:
        c.write('InvName' + ',InvID' + '\n')
    missinginvnames = []
    with open("KeyAndItemNameTwoColumns.csv","rb") as fp:
        reader = csv.reader(fp, skipinitialspace=True)
        fp.readline() # skip header
        invidsandnames = {int(id): str.upper(name) for id, name in reader}
    invids = set(invidsandnames.keys())
    invnames = set(invidsandnames.values())
    invonhandset = set(inventory)
    missinginvidsset = invids - invonhandset
    missinginvids = list(missinginvidsset)
    missinginvnames = getNames(invidsandnames, missinginvids)
    missinginvnameswithids = dict(zip(missinginvnames, missinginvids))
    print missinginvnameswithids
    with open(csvfile,'a') as c:
        for invname, invid in missinginvnameswithids.iteritems():
            c.write(invname + ',' + str(invid) + '\n')

    return missinginvnameswithids

次に、次のように呼び出します。

InventoryNumbers(invlist)

その説明で、ここで私の質問に移りましょう。追加の列を追加して、この出力 .csv ファイルのデータを拡張したいと考えています。このデータは別の .csv ファイルから取得され、そのスニペットは次のようになります。

100001,fruit,medium,12,red
100002,vegetable,medium,10,orange
100003,fruit,medium,14,green
100004,fruit,medium,12,yellow
100005,vegetable,small,10,red

これにはアイテム名が含まれていないことに注意してください (そのため、キーとアイテム名の 2 つの列だけを持つ別の .csv ファイルからプルする必要があります) が、同じキーを使用しています。この追加情報を取り込む方法を探しています。これにより、最終的な .csv ファイルが、在庫にないアイテムのキー (アイテム ID) とアイテム名だけでなく、タイプ、サイズ、数、色の列。

私が調べた 1 つのオプションは、コレクションのdefaultdict部分ですが、これが私がやりたいことを実行するための最良の方法であるかどうかはわかりません。このメソッドを使用した場合、目的の結果を得るためにどのように呼び出すか正確にはわかりません。他の方法が簡単であれば、私もそれを試してみたいと思っています.

インベントリにないアイテムのキーと対応するアイテム名の dict を取得し、すべてを .csv ファイルに出力できるように、この追加情報を追加するにはどうすればよいですか?

編集:これを入力すると、キー、アイテム名、タイプ、サイズ、番号、色の形式で日付を持つ新しい単一の.csvファイルを作成することで、自分で物事を簡単にすることができると思いました(基本的にはコピーするだけですアイテム名の列にある .csv に、各キーの他の情報が既に含まれています。) この方法では、2 つではなく 1 つの .csv ファイルから描画するだけで済みます。ただし、これを行ったとしても、インベントリにないアイテムのキーのみに基づいて、目的の .csv ファイルを作成するにはどうすればよいでしょうか?

回答:受け入れたソリューションを実装する方法についてここに別の質問を投稿しました(最初からdict値がセットではなく文字列であったため、値エラーが発生したため)、セットではなくリストが必要であると判断しました(順序を維持するため。) また、1 つの .csv ファイルから描画するだけで済むように、他のすべてのデータを含む .csv ファイルにアイテム名の列を追加することになりました。とはいえ、コードのこのセクションは次のようになります。

MyDict = {}
infile = open('FileWithAllTheData.csv', 'r')
for line in infile.readlines():
    spl_line = line.split(',')
    if int(spl_line[0]) in missinginvids: #note that this is the list I was using as the keys for my dict which I was zipping together with a corresponding list of item names to make my dict before.
        MyDict.setdefault(int(spl_line[0]), list()).append(spl_line[1:])
print MyDict
4

3 に答える 3

1

必要なのは、intをセットにマッピングする辞書、つまり、

MyDict = {100001: set([apple]), 100002: set([carrot])}

更新で追加できます:

MyDict[100001].update([fruit])

それはあなたに与えるでしょう:{100001: set([apple, fruit]), 100002: set([carrot])}

また、ニンジンの属性のリストがあれば...[vegetable,orange]

あなたは言えたMyDict[100002].update([vegetable, orange])

そして得る:{100001: set([apple, fruit]), 100002: set([carrot, vegetable, orange])}

これはあなたの質問に答えていますか?

編集:

CSVに読み込む...

infile = open('MyFile.csv', 'r')
for line in infile.readlines():
    spl_line = line.split(',')
    if int(spl_line[0]) in MyDict.keys():
        MyDict[spl_line[0]].update(spl_line[1:])
于 2012-11-08T04:24:34.970 に答える
1

これは質問に対する答えではありませんが、現在のコードを単純化する方法を次に示します。

これ:

invids = set(invidsandnames.keys())
invnames = set(invidsandnames.values())
invonhandset = set(inventory)
missinginvidsset = invids - invonhandset
missinginvids = list(missinginvidsset)
missinginvnames = getNames(invidsandnames, missinginvids)
missinginvnameswithids = dict(zip(missinginvnames, missinginvids))

次のものに置き換えることができます。

invonhandset = set(inventory)
missinginvnameswithids = {k: v for k, v in invidsandnames.iteritems() if k in in inventory}

または:

invonhandset = set(inventory)
for key in invidsandnames.keys():
    if key not in invonhandset:
        del invidsandnames[key]
missinginvnameswithids = invidsandnames
于 2012-11-08T04:33:23.680 に答える
0

一時的な RDB (python にはsqlite サポートが組み込まれています) を作成することを検討しましたか?妥当な数のアイテムについては、パフォーマンスの問題はないと思います。

各 CSV ファイルと web-api からの結果をテーブル (データ ソースごとに 1 つのテーブル) に変換します。その後、いくつかの SQL クエリ + 結合を使用して、やりたいことをすべて行うことができます。必要なデータを取得したら、それを CSV にダンプできます。

于 2012-11-08T04:21:13.790 に答える