0

同様の形式に従う何百ものファイルを解析しています。このファイルから、2 つのキー、または値がセットになっている 3 つ以上のキーを含む辞書を作成します。とにかく、「Y」値を含むキーが常に存在します。そのキーについては、他のキーに存在する重複値を削除する必要があります。

キーが2つしかないという同様の問題があり、解決されました。Python:辞書内の異なるキーの値を比較してから重複を削除する方法は?

以下のコードは、ディクショナリに 2 つのキーがあり、2 つ以下の場合に正常に機能します。

for d, p in zip(temp_list, temp_search_list):
    temp2[d].add(p) #dictionary with delvt and pin names for cell
for test_d, test_p in temp2.items():
    if not re.search('Y', ' '.join(test_p)) :
         tp = temp2[test_d]
    else:
         temp2[test_d] = [t for t in temp2[test_d] if t not in tp]

3 つのキーを使用する辞書の例ですが、解析されたファイルによっては、より多くのキーを使用できます。

temp2 = {'0.1995': set(['X7:GATE', 'X3:GATE', 'IN1']), '0.199533': set(['X4:GATE', 'X8:GATE', 'IN2']), '0.399': set(['X3:GATE', 'X5:GATE', 'X1:GATE', 'IN0', 'X4:GATE', 'Y', 'X8:GATE'])}

期待される出力:

temp2
{'0.1995': set(['X7:GATE', 'X3:GATE','IN1']), '0.199533': set(['X4:GATE', 'X8:GATE', 'IN2']), '0.399': set(['X5:GATE', 'X1:GATE', 'IN0', 'Y'])}
4

4 に答える 4

1

実際にデータセット全体をトラバースする必要がある 1 つのループだけですべてを実行できます。

from collections import defaultdict

target = None
result = defaultdict(set)
occurance_dict = defaultdict(int)
# Loop over the inputs, building the result, counting the
# number of occurances for each value as you go and marking
# the key that contains 'Y'
for key, value in zip(temp_list, temp_search_list):
    # This is here so we don't count values twice if there
    # is more than one instance of the value for the given
    # key.  If we don't do this, if a value only exists in
    # the 'Y' set, but it occurs multiple times in the input,
    # we would still filter it out later on.
    if value not in result[key]:
        occurance_dict[value] += 1
        result[key].add(value)
    if value == 'Y':
        if target is None:
            target = key
        else:
            raise ValueError('Dataset contains more than 1 entry containing "Y"')
if target is None:
    raise ValueError('Dataset contains no entry containing "Y"')
# Filter the marked ('Y' containing) entry; if there is more than
# 1 occurance of the given value, then it exists in another entry
# so we don't want it in the 'Y' entry
result[target] = {value for value in result[target] if occurance_dict[value] == 1}

はいoccurance_dictは a とほぼ同じですが、collections.Counter必要がない場合は (舞台裏で発生していても) データセットを 2 回反復したくありません。同じキーの値。

于 2013-01-16T16:01:40.820 に答える
1

Y値の検索と、残りのデータの検索を分離する必要があります。temp2不必要なループを避けるために、すでに を構築しているときに本当にそれを行いたいです:

y_key = None
for d, p in zip(temp_list, temp_search_list):
    temp2[d].add(p)
    if p == 'Y':
        y_key = d

set.difference_update()次に、セットをインプレースで変更することを使用して、重複値を削除するのが最も簡単です。

y_values = temp2[y_key]
for test_d, test_p in temp2.iteritems():
    if test_d == y_key:
        continue
    y_values.difference_update(test_p)

あなたの例を使用し、ビルド中にすでに設定されているtemp2と仮定すると、2番目のループの結果は次のようになります。y_keytemp2

>>> temp2 = {'0.1995': set(['X7:GATE', 'X3:GATE', 'IN1']), '0.199533': set(['X4:GATE', 'X8:GATE', 'IN2']), '0.399': set(['X3:GATE', 'X5:GATE', 'X1:GATE', 'IN0', 'X4:GATE', 'Y', 'X8:GATE'])}
>>> y_key = '0.399'
>>> y_values = temp2[y_key]
>>> for test_d, test_p in temp2.iteritems():
...     if test_d == y_key:
...         continue
...     y_values.difference_update(test_p)
... 
>>> temp2
{'0.1995': set(['X7:GATE', 'X3:GATE', 'IN1']), '0.199533': set(['X4:GATE', 'X8:GATE', 'IN2']), '0.399': set(['X5:GATE', 'X1:GATE', 'IN0', 'Y'])}

X3:GATEX4:GATE、がセットX8:GATEから削除されていることに注意してください0.399

于 2013-01-16T16:02:29.190 に答える
0

リスト内包表記や itertools モジュールを使ってこれを行うかわいい方法を考えられたらいいのにと思いますが、できません。私は次のようなものから始めます:

dict1 = {1: set([1,2,3,4,5]),
         2: set([3,4,5,6]),
         3: set([1,7,8,9])
        }

list1 = dict1.items()
newDict = {}
for i in range(len(list1)):
    (k1,set1) = list1[i]
    newDict[k1] = set1
    for j in range(i+1,len(list1)):
        (k2, set2) = list1[j]
        newDict[k2] = set2 - (set1 & set2)

print newDict 
# {1: set([1, 2, 3, 4, 5]), 2: set([6]), 3: set([8, 9, 7])}

巨大な辞書がある場合、これはおそらくあまり効率的ではありません。

別のアイデア: セットが長すぎて、単に を形成できませんcollection.Counterか? 最初にdictを調べて、各セットのメンバーを取り除き、それらをカウンターに貼り付けます(おそらく、リスト内包表記を使用して1行で実行できます)。次に、 をループしoriginalDict.iteritems()ます。新しい dict に、値が元のセットであるキー (つまり、0.1995) を挿入できます。その値はフィルター処理され (&上記のように使用すると思います)、カウント > 0 のカウンター内のエントリのみが含まれるようになります。新しい辞書に挿入された場合、それらをカウンターから削除します (カウントが 1 を超えていても)。結局のところ、それでも 2 回ループする必要があります。

于 2013-01-16T16:26:55.917 に答える
0

私にはかなり簡単に思えます。まず、値のセットに a を持つキーを見つけて'Y'から、他のすべての値のセットを調べて、その値のセットからそれらを削除します。

temp2 = {'0.1995':  set(['X7:GATE', 'X3:GATE', 'IN1']),
         '0.199533':set(['X4:GATE', 'X8:GATE', 'IN2']),
         '0.399':   set(['X3:GATE', 'X5:GATE', 'X1:GATE', 'IN0', 'X4:GATE', 'Y', 'X8:GATE'])}

y_key = None
for k,v in temp2.iteritems():
    if 'Y' in v:
        y_key = k
        break

if y_key is None:
    print "no 'Y' found in values"
    exit()

result = {}
for k,v in temp2.iteritems():
    if k != y_key:
        temp2[y_key] -= v

print 'temp2 = {'
for k,v in temp2.iteritems():
    print '  {!r}: {!r},'.format(k,v)
print '}'

出力:

temp2 = {
  '0.1995': set(['X7:GATE', 'X3:GATE', 'IN1']),
  '0.199533': set(['X4:GATE', 'X8:GATE', 'IN2']),
  '0.399': set(['X5:GATE', 'X1:GATE', 'IN0', 'Y']),
}
于 2013-01-16T17:40:03.977 に答える