3

次のような一連のデータがあります。

data = { 1: {"root": [2],
             "leaf": [10, 11, 12],
             },
         2: {"root": [1,3],
             "leaf": [13, 14, 15],
             },
         3: { "root": [2],
              "leaf": [16, 17],
            },
         4: {"root": [],
             "leaf": [17, 18, 19],
             },
         5: { "root": [],
              "leaf": [20, 21]
             },
       }

このデータから、最初のキーはルート ノード インデックスであり、どのルート ノードとリーフ ノードが関連しているかを説明するディクショナリが含まれています。

すべてのインデックスを関連リストにマージしたいと考えています。

  • ルート インデックスによって接続されたルート インデックス、両方/すべてのルート インデックス、およびすべてのリーフ インデックスが、結果のリストにマージされます。
  • ルート インデックスは、リーフを介して別のルートに接続できます。ルート インデックスとすべてのリーフ インデックスは、結果のリストにマージされます。

データをトラバースしてマージする最良の方法を見つけるのに少し苦労しています。上記のデータセットから、期待される出力は次のとおりです。

[[1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], [5, 20, 21]]

Fixed Attemptは機能しているようですが、より効率的な方法はありますか?

class MergeMachine(object):
    processed = []

    def merge(self, idx, parent_indexes, existing):
        if idx not in self.processed:
            parent_indexes.append(idx)
            if self.data[idx]["root"]:
                for related_root_idx in self.data[idx]["root"]:
                    if related_root_idx not in self.processed and related_root_idx not in parent_indexes:
                        existing.extend(self.merge(related_root_idx, parent_indexes, existing))
                        self.processed.append(related_root_idx)
            existing.append(idx)
            existing.extend(self.data[idx]["leaf"])
            self.processed.append(idx)
        return existing

    def process(self, data):
        results = []
        self.data = data
        for root_idx in self.data.keys():
            r = set(self.merge(root_idx, [], []))
            if r:
                combined = False
                for result_set in results:
                    if not r.isdisjoint(result_set):
                        result_set.union(r)
                        combined = True
                if not combined:
                    results.append(r)
        return results

mm = MergeMachine()
mm.process(data)

データを期待される出力にマージする効率的な方法はありますか?

4

2 に答える 2

3

これが効率的かどうかはわかりませんが、うまくいくようです:

data = #your data as posted

data = [set ( [k] ) | set (v ['root'] ) | set (v ['leaf'] ) for k, v in data.items () ]
merged = []
while data:
    e0 = data [0]
    for idx, e in enumerate (data [1:] ):
        if e0 & e:
            data [idx + 1] = e | e0 #idx is off by 1 as I enumerate data [1:]
            break
    else: merged.append (e0)
    data = data [1:]

print (merged)

最悪のシナリオ (つまり、マージの可能性がない) では、コストは O(n**2) になるはずです。そして、再帰なしのシリアルです。

于 2013-02-20T03:39:16.533 に答える
1

これは上記のものと似ていますが、まったく同じではありません。私の破壊的で、入力データ構造を消費し、同じポイントで制限されていると思います(入力データがどれも関連していない場合はOn ^ 2)。

def merge(data):
  result = []
  while data:
    k, v = data.popitem()
    temp = set([k]) | set(v['root']) | set(v['leaf'])
    for idx, test in enumerate(result):
      if test & temp:
        result[idx] |= temp
        break
    else:
      result.append(temp)
  return result
于 2013-02-20T04:56:19.630 に答える