2016-05-04 9 views
2

テーブルの2つの列の間に1対1の関係があります。たとえばCi <--> Cjです。Pythonでの高速検索のための1対1リレーションシップテーブルの格納方法

高速検索のためにこのようなテーブルを保存するにはどうすればよいですか?私は次のコードスニペットを使って自分自身をはっきりと表現します。

C1 = [1, 2, 3, 4] 
C2 = ['a', 'b', 'c', 'd'] 
C3 = ['one', 'two', 'three', 'four'] 

# lookup, Ci --> Cj 
idx = Ci.index(val) 
corresponding_val = Cj[idx] 

Dictが良い選択です。例として2列だけのテーブルを用意し、テーブルを辞書として保存します。具体的には、d[C1] = C2とします。 からC2にはO(1)が必要です。しかし、C2からC1までは、時間がかかります。

+0

どのように2つのディクテーションを1つずつ持つのはどうですか?または、それぞれの関係が二度、一度一度二回あるdict? – ddsnowboard

+0

@ddsnowboard、それは2つの列のために働く。しかし、* n *列の場合、* n *(n-1)* dictsが必要です。 – SparkAndShine

答えて

4

C1、C2、C3のいずれかでキーをすばやく検索する必要がある場合は、3つの辞書を使用します。それぞれの値は3タプルです。

all = zip(C1, C2, C3) 
d1,d2,d3 = {},{},{} 
for v in all: 
    d1[ v[0]], d2[v[1]], d3[v[2]] = v,v,v 

使用法:

>>> d3['three'] 
(3, 'c', 'three') 
>>> d1[1] 
(1, 'a', 'one') 
>>> d2['a'] 
(1, 'a', 'one') 

これはタプルデータのひとつのセットにアクセスする3つのインデックスであるので、それはあなたが各高速検索のための1つのハッシュインデックスを必要とすることを与えることができると同じくらい効率的です。

assert d1[1] is d2['a'] and d1[1] is d3['one'] 

アクセスされるのは行全体なので、各列に必要なdictは1つだけです。ただし、どの列にも重複する値がないという前提があります。重複が存在する可能性がある場合は、取得された各値は、単なる唯一の行タプルではなく、行タプルのリストである必要があります。これを必要とする場合は、設定するのがもっと難しくありません。

C2=['odd','even','odd','even'] 
... 
for v in all: 
    d1.setdefault(v[0],[]).append(v) 
    d2.setdefault(v[1],[]).append(v) 
    d3.setdefault(v[2],[]).append(v) 

>>> d2 
{'even': [(2, 'even', 'two'), (4, 'even', 'four')], 'odd': [(1, 'odd', 'one'), (3, 'odd', 'three')]}  
+1

すべてのキーを1つの辞書にマージすると便利です。代入を 'd [v [0]]、d [v [1]]、d [v [2]] = v'に変更してください。この場合、あなたは 'd [C1 [i]]'や 'd [C2 [i]]'や 'd [C3 [i]]'を実行するだけです。 –

+0

@John Carpenterはい、それはすべての列の合併に重複した値がない限り動作します。存在する場合、 'setdefault'を使ってリストを構築し、一致する行をすべて検索して一致が正しい列にあるかどうかを確認しても、それでも機能します。 – nigel222

1

すべての列を一意のリストに入れてください。種類の:

D = zip(C1, C2, C3,...) 

あなたは、Dの最初の要素をループすることができます。このようにcomprehesionリストを使用して、あなたが必要とする他の人を返します。

+1

"高速検索"は、リニア検索よりも優れていることを意味します。ハッシュテーブルは、辞書が提供するものです。検索はO(N)です。ハッシュテーブルはO(1)であるか、または大きなN、O(ln N)に対して最悪である。 – nigel222

+0

Yep @ nigel222。私はそれを忘れてしまった、私のせいだ。 確かに、ハッシュを使うのはいつもより良いです...だから、ハッシュを使わないで許容できる解決策は何でしょうか?それは、リストを注文するためにalgorythmを使用します(バイナリツリーソート、...)、あなたは結果を検索するために別のalgorythmを使用することができます...あなたがいくつかの検索を行う必要がある場合、 (n log n)(1回)とO(log n)となる。 –

+1

Pythonを使用していて、すべてがメモリに収まっている場合は、dictを使い、良いハッシュアルゴリズムと内部データ構造を選んだPythonを開発している人に頼ってください。 Pythonを使用しない場合...私はかつて64ビットリストの1つから16ビットのハッシュ値を選択しました。ほとんどのハッシュ値は、単一要素のリストに対処しました。これは、索引付けするものが約4万件あったからです。なぜなら、私が自分自身をロールバックしなければならなかったのは、これまでのプログラマーがこれまでに予想していたものよりも使用されていた古代のFortranのコードだったのです。一般に、すでに図書館のコードがあります! – nigel222