2

複雑なリレーション (SQL を使用していない) を含む 2 つの階層データセットを使用しており、プライマリ ルックアップ キーを共有していません。このプロセスを使用して、2 つのデータセットの同期を維持します。

各データセットは現在、データセットのキーをディクショナリのキーとして持つディクショナリとして保存されています。複雑な関係が決定された後、他のデータセットのキーを属性として他のデータセットに保存します。これにより、いくつかの奇妙なヘルパー関数を作成して、いくつかの親子関係をたどる必要が生じました。

現在、関係を解析する必要がある処理関数に両方のデータセットを渡す必要があるため、この狂気に対してより効果的または高速な方法があるかどうか疑問に思っていました。

例:

leftdataset = {'10000': { 'key': '10000', 'fkey':'asdf', 'parent':'10001'},
               '10001': { 'key': '10001', 'fkey':'qwer', 'parent':''},}
rightdataset= {'asdf': { 'key': 'asdf', 'fkey':'10000', 'parent':'qwer'},
               'qwer': { 'key': 'qwer', 'fkey':'10001', 'parent':''},

親を見つけるには、次のfkeyことが必要です。

fkey = dataset[dataset['10000']['parent']]['fkey']

キーペアのタプルを提示し、その中で必要なキーを次のように探すというアイデアをいじっていました。

keys = [('10000', 'asdf'), ('10001', 'qwer')]

def find_key(key, keyset):
  for keypair in keys:
    if key in keypair:
      k1, k2 = keypair
      if k1 == key:
        return k2
      else:
        return k1

しかし、これは私が現在行っていることよりも効率が悪いように思えます。私は間違った道をたどっているだけですか?

4

2 に答える 2

2

Mark Ransom のコメントに基づいて、次のようなクラスを編成できます。

class Storage(object):

    def __init__(self):

        self._leftdataset = {
            '10000': { 'key': '10000', 'fkey':'asdf', 'parent':'10001'},
            '10001': { 'key': '10001', 'fkey':'qwer', 'parent':''}
        }

        self._rightdataset= {
            'asdf': { 'key': 'asdf', 'fkey':'10000', 'parent':'qwer'},
            'qwer': { 'key': 'qwer', 'fkey':'10001', 'parent':''}
        }

    def get(self, key):
        d1 = self._leftdataset
        d2 = self._rightdataset

        if key in d1:
            left = d1[key]
            right = d2[left['fkey']]
        else:
            right = d2[key]
            left = d1[right['fkey']]

        return left, right

そして、単一の検索方法を使用します。

s = Storage()

s.get('10000')
# ({'fkey': 'asdf', 'key': '10000', 'parent': '10001'},
#  {'fkey': '10000', 'key': 'asdf', 'parent': 'qwer'})


s.get('qwer')
# ({'fkey': 'qwer', 'key': '10001', 'parent': ''},
#  {'fkey': '10001', 'key': 'qwer', 'parent': ''})
于 2012-08-29T00:03:29.177 に答える
1

この使用法はあなたにとって魅力的ですか?

単一エントリの簡単な検索と使用:

>>> left("10000")
Entry({'parent': '10001', 'key': '10000', 'fkey': 'asdf'})
>>> left("10000")['key']
'10000'
>>> left("10000")['parent']
'10001'

親の簡単な検索:

>>> left("10000").parent()
Entry({'parent': '', 'key': '10001', 'fkey': 'qwer'})
>>> left("10000").parent().parent()
>>> left("10001")
Entry({'parent': '', 'key': '10001', 'fkey': 'qwer'})
>>> left("10001") is left("10000").parent()
True

関連エントリの簡単な検索:

>>> left("10001").related()
Entry({'parent': '', 'key': 'qwer', 'fkey': '10001'})
>>> right("qwer")
Entry({'parent': '', 'key': 'qwer', 'fkey': '10001'})
>>> right(left("10001").related()['key'])
Entry({'parent': '', 'key': 'qwer', 'fkey': '10001'})
>>> right("qwer") is left("10001").related()
True

特にあなたの質問の例は次のとおりです: 親の外部キー:

>>> left("10000").parent()['fkey']
'qwer'

もしそうなら、ここにコードがあります!クラス:

class Entry(object):
    def __init__(self, dataset, d):
        self.dataset = dataset
        self.d = d

    def parent(self):
        return self.dataset.parent_of(self)
    def related(self):
        if not self.dataset.related_dataset:
            raise ValueError("no related dataset specified")
        return self.dataset.related_dataset(self['fkey'])

    def __getitem__(self, k):
        return self.d.__getitem__(k)

    def __repr__(self):
        return "Entry(%s)" % repr(self.d)
    def __str__(self):
        return str(self.d)

class Dataset(object):
    def __init__(self, data):
        self.data = dict((k, Entry(self, v)) for (k,v) in data.items())
        self.related_dataset = None

    def set_related_dataset(self, dataset):
        self.related_dataset = dataset

    def entry(self, key):
        if isinstance(key, Entry): return key
        return self.data[key]
    def __call__(self, key):
        return self.entry(key)

    def parent_of(self, entry):
        entry = self.entry(entry)

        if not entry['parent']:
            return None
        return self.data[entry['parent']]

そして、あなたが提供したデータの使用法:

leftdata = {'10000': { 'key': '10000', 'fkey':'asdf', 'parent':'10001'},
               '10001': { 'key': '10001', 'fkey':'qwer', 'parent':''},}
rightdata = {'asdf': { 'key': 'asdf', 'fkey':'10000', 'parent':'qwer'},
               'qwer': { 'key': 'qwer', 'fkey':'10001', 'parent':''}}

left = Dataset(leftdata)
right = Dataset(rightdata)
left.set_related_dataset(right)
right.set_related_dataset(left)

Entry説明: 各辞書値を定義済みのクラスにラップ__getitem__して、辞書として (多かれ少なかれ) 使用できるようにします。Dataset主キーをこれらの にマップするクラスを用意しますEntryEntryこのデータセットへのアクセスを提供し、便利なメソッド.parent()とを提供し.related()ます。が機能するため.related()には、「関連する」データセットをどのデータセットに含めるかを設定しset_related_dataset、すべてを結び付けます。

s を渡すだけでもEntry、両方のデータセットを渡す必要なく、関連するエントリにアクセスできるようになりました。

于 2012-08-29T00:28:10.220 に答える