0

私は同様の質問をしました (キーを削除せずに辞書から重複値を削除します)、残念ながら、私が必要としていた答えはどれもありませんでしたが、彼らは私の答えを出しました。質問。

2 つの .csv ファイルから OrderedDict を構築しています。1 つ目は場所コードを含み、2 つ目は時間ごとのハードウェア再配置のリストです。すべての場所コードは一意であるため、それが私の辞書の鍵です。その .csv ファイルを使用して、空の値で辞書を作成するループがあります。次に、ハードウェア データを正しいロケーション コードに追加する別のループがあります。一部のハードウェア データはリスト形式であるため、ハッシュできません。

私が抱えている問題は、ハードウェアが新しい場所に移動するときに、以前の場所から削除する必要があることです。そのため、コードの最後の 1 か所だけに

私のロケーションコードは;

>1, 2, 3, 4, 5, 6

私のハードウェアデータは時間順に並んでいます。

>7pm, 1, 'item1', 'item2', 'item3'
>8pm, 2, 'item4', 'item5', 'item6'  
>9pm, 3, 'item7', '', ''
>10pm, 4, 'item8', '', ''
>11pm, 5, 'item1', 'item2', 'item3'
>12am, 6, 'item7', '', ''
>1am, 3, 'item4', 'item5', 'item6'

条件ステートメントなしでタイムフレーム全体のコードを実行すると、最終的な辞書は次のようになります

>myDict = {'1': ['item1', 'item2', 'item3'], '2': ['item4', 'item5', 'item6'],  
>'3': 'item7', '4': 'item8', '5': ['item1', 'item2', 'item3'], '6': 'item7'}

しかし、私がそれを必要としているのも次のとおりです。

>my Dict = {'1': '', '2':'', '3': ['item4', 'item5', 'item6'], '4':  
>'item8', '5': ['item1', 'item2', 'item3'], '6': 'item7'}

項目 (値) は場所 (キー) が追加される順序と同じ順序でディクショナリに追加されないため、ディクショナリを作成 (値を追加) しながらこれを行うことが重要です。完了後に重複を削除します。

私は多くのことを試し、異なる結果を得ましたが、私の最新のものは

locationCSV =  open('location.csv', "r")
hardwareCSV =  open('hardware.csv', "r")
locationLines = locationCSV.readlines()
hardwareLines = hardwareCSV.readlines()
finalLoc = OrderedDict() 

for line in locationLines:
    locationList = line.split(",")
    code = locationList[0]
    finalLoc[code] = ""

for line in hardwareLines:
    hardwareList = line.split(",")
    hardwareData = [hardwareList[2],hardwareList[3],hardwareList[4]]
    for k, v in finalLoc.iteritems():
        if hardwareData in finalLoc.itervalues():
            finalLoc[k] = ""
    finalLoc[hardwareList[1]] = hardwareData

print finalLoc

これにより、すべての場所が空になります。私はこれに数日間立ち往生しているので、助けていただければ幸いです。

4

3 に答える 3

0

コードには多くの問題があり、そこまで到達することさえできないため、これが実際のコードである可能性はありません。しかし、エラーを見てみましょう:


csvList = line.split(",")

" 1"これにより、とのような値が得られますが" 'item1'"、これが実際に必要なものであるとは想像できません。

実際、行の最後に空白があるということは、行が一致しないことを意味します。たとえば、2 行目の最後の文字列は です" 'item6' "が、最後の行" 'item6'"は であり、同じ文字列ではありません。

csv自分でやろうとするのではなく、ライブラリを使用すると、これははるかに簡単になります。問題を解決するために簡単なハックが必要な場合は、strip各エントリを次のように入力できます。

csvList = [item.strip() for item in line.split(",")]

hardwareData = [csvList[2],csvList[3],csvList[4]]

一部の行には 3 列しかないため、これによりIndexError. 値を上げるのではなく、短い行で 3 つ未満の値を取得したい場合は、次のようにします。

hardwareData = csvList[2:5]

for k, v in finalLoc.iteritems():
    if hardwareData in finalLoc.itervalues():

行ごとに辞書全体を調べ、エントリごとに辞書全体を検索して、finalLocどこかに値があるかどうかを確認します。したがって、dict に既に 10 個の項目がある場合、既に 100 回存在する各行を見つけることになります。つまり、見つけたものを行ごとに空白にすると、すべての行を 10 回空白にすることになります。

あなたはおそらくここにいたかったでしょうif hardwareData == v


        finalLoc[key] = ""

key表示されたコードのどこにも定義していません。以前のどこかで定義した場合、各行で 100 回ごとに同じ値が空白になります。それ以外の場合、これは単に a を発生させNameErrorます。

あなたはおそらくここにいたかったでしょうfinalLoc[k]

逆辞書を保持し、各値をそのキーにマッピングすると、この部分全体がはるかに単純になります (そしてより効率的になります)。


とにかく、これらすべての修正をまとめると、コードは機能します。

from collections import OrderedDict

hardwareLines = """7pm, 1, 'item1', 'item2', 'item3'
8pm, 2, 'item4', 'item5', 'item6'  
9pm, 3, 'item7'
10pm, 4, 'item8'
11pm, 5, 'item1', 'item2', 'item3'
12am, 6, 'item9'
1am, 3, 'item4', 'item5', 'item6'""".splitlines()

finalLoc = OrderedDict() 

for line in hardwareLines: ##hardware is the second .csv
    csvList = [item.strip() for item in line.split(",")]
    hardwareData = csvList[2:5]
    for k, v in finalLoc.iteritems():
        if hardwareData == v:
            finalLoc[k] = ""
    finalLoc[csvList[1]] = hardwareData

for k, v in finalLoc.iteritems():
    print('{}: {}'.format(k, v))

出力は次のとおりです。

1: 
2: 
3: ["'item4'", "'item5'", "'item6'"]
4: ["'item8'"]
5: ["'item1'", "'item2'", "'item3'"]
6: ["'item9'"]

csvモジュールと逆マッピングを使用したバージョンを次に示します。

from collections import OrderedDict
import csv

hardwareLines = """7pm, 1, 'item1', 'item2', 'item3'
8pm, 2, 'item4', 'item5', 'item6'  
9pm, 3, 'item7'
10pm, 4, 'item8'
11pm, 5, 'item1', 'item2', 'item3'
12am, 6, 'item9'
1am, 3, 'item4', 'item5', 'item6'""".splitlines()

finalLoc = OrderedDict()

invmap = {}

for row in csv.reader(map(str.rstrip, hardwareLines), 
                      skipinitialspace=True, quotechar="'"):
    hardwareData = tuple(row[2:5])
    if hardwareData in invmap:
        finalLoc[invmap[hardwareData]] = ""
    finalLoc[row[1]] = list(hardwareData)
    invmap[hardwareData] = row[1]

for k, v in finalLoc.iteritems():
    print('{}: {}'.format(k, v))

各行の余分な末尾の空白を明示的に削除する必要がありましたが、それ以外csvはすべて処理してくれました。また、各値の周りの余分な引用符も削除されていることに注意してください。

一方、アイテムを調べて現在の値に一致するすべてのキーを見つける方法を理解する必要はなく、invmap1 つのステップで検索できます。(マッピングは 1 対 1 でなければならないことに注意してください。値が既に 2 回発生している場合、最初の値は既に削除されているためです。)


もちろん、ストリッピングとクォートの問題を修正しても、結果は依然として希望どおりにはなりません。目的の出力は、単一要素リストを要素だけに展開しているようです。それが必要な場合は、明示的に行う必要があります。しかし、あなたはおそらくそれを望んでいません。実際、おそらく「空の」値としての[]代わりに使用したいと思うでしょう。''そうすれば、空の文字列を 0 の値として、その他の文字列を 1 つの値として、リストを複数の値として扱うのではなく、値が常に0 個以上の項目のリストであることがわかります。したがって、それを処理するときは、次のようなコードを書く代わりに:

if value == '':
    return ''
elif isinstance(value, str):
    return process_one_value(value)
else:
    return map(process_one_value, value)

…これを行うことができます:

return map(process_one_value, value)
于 2013-08-27T20:44:12.563 に答える
0

注文辞書の維持に重点を置いた、簡単で汚いバージョンです。入力データの読み取りと解析を処理する csv モジュールがあります。

def removeItem(d, item):
    # remove item from d, if present
    for k,v in d.items():
        if item in v:
            v.remove(item)
            d[k] = v

d=OrderedDict()
for c in loc_codes: #['1','2',....]
    d[c]=[]
for line in hardware.split('\n'): # or read line from file
    if line:
        items = line.split(', ')
        items = [l.strip("'") for l in items]
        k = items[1].strip()
        v = items[2:]
        for item in v:
            removeItem(d,item)
            d[k] += [item]
print d

結果:

OrderedDict([('1', []), ('2', []), ('3', ['item7', 'item4', 'item5', 'item6']), ('4', ['item8']), ('5', ['item1', 'item2', 'item3']), ('6', ['item9'])])

[]リストからアイテムを簡単に追加および削除できるように、値から始めます。それが重要な場合は、[]値を簡単に変更できます。''大規模なデータ セットの場合、removeItemセットやその他の辞書を使用するものほど効率的ではありませんが、作業を進めるための迅速かつ明白な方法です。さらに、他のデータ構造に依存しません。

于 2013-08-27T21:19:04.697 に答える
-1

これの解析の側面について心配するつもりはありません。したがって、次のような使用可能な形式にデータが読み込まれていると仮定しましょう。

locations = [1, 2, 3, 4, 5, 6]
hardware = [
    ('7pm',  1, ['item1', 'item2', 'item3']),
    ('8pm',  2, ['item4', 'item5', 'item6']),
    ('9pm',  3, ['item7']),
    ('10pm', 4, ['item8']),
    ('11pm', 5, ['item1', 'item2', 'item3']),
    ('12am', 6, ['item9']),
    ('1am',  3, ['item4', 'item5', 'item6'])
]

(解析コードをデータ処理コードから分離することを強くお勧めします。アルゴリズムが CSV 解析コードと混ざっていなければ、アルゴリズムを推論するのははるかに簡単です。)

これを解決するための鍵は、データを処理する際に 2 つの辞書を維持することです。1 つは場所をそれらの場所にあるアイテムのリストにマッピングし、もう 1 つはアイテムをそれらの場所にマッピングします。2 番目のマップは、最初のマップの逆です。

これらの逆マップを使用すると、どちらの方向でも情報を検索できます。場所があればそこにあるアイテムを確認でき、アイテムがあればその場所を取得できます。

items_by_location = dict()   # The items in each location.
locations_by_item = dict()   # The location of each item.

# Start with an empty set for the list of items in each location.
for location in locations:
    items_by_location[location] = set()

# Iterate over each item in each hardware line one by one.
for time, location, items in hardware:
    for item in items:
        old_location = locations_by_item.get(item)
        new_location = location

        # Remove the item from its old location.
        if old_location:
            items_by_location[old_location].remove(item)

        # Add it to its new location.
        items_by_location[new_location].add(item)
        locations_by_item[item] = new_location

# Now we can iterate over the list and see where each item ended up.    
for location, items in items_by_location.items():
    print location, items

出力:

1 set([])
2 set([])
3 set(['item6', 'item7', 'item4', 'item5'])
4 set(['item8'])
5 set(['item2', 'item3', 'item1'])
6 set(['item9'])
于 2013-08-27T20:31:42.873 に答える