2012-02-17 9 views
0

辞書を作成するのにPythonを使用していましたが、データが大きくなるにつれてメモリエラーが発生し始めたので、メモリを節約して、結果は同じではありません。私はこれがdefaultdictの動作と関係していると思います(しかし私は分かりません)。同様のコマンドでpythonとmysqlの結果が異なっています

ここで作業Pythonのコード(それは基本的に値のテーブルを作成します)です。結果は(あなたがコメントで内訳を見ることができる値の大きなテーブルで

from collections import defaultdict 
data = [2,5,10] 
target_sum = 100 
# T[x, i] is True if 'x' can be solved 
# by a linear combination of data[:i+1] 
T = defaultdict(bool)   # all values are False by default 
T[0, 0] = True    # base case 

for i, x in enumerate(data): # i is index, x is data[i] 
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself 
     for c in range(s/x + 1): 
      if T[s - c * x, i]: 
       T[s, i+1] = True 

#check the python dict results 
count = 0 
for x in T: 
    if T[x] == True: 
     print x, ':', T[x] 
     count = count +1 

print 'total count is ', count 
#False is 152 and True is 250. Total is: 402 

これは正しい結果である私は。しかし、最初のfor文の最後の行をローカルdictではなくデータベースに追加するように変更すると、結果が異なります。

cursor = conn.cursor() 
cursor = conn.cursor() 
cursor.execute ("DROP TABLE IF EXISTS data_table") 
cursor.execute (""" 
    CREATE TABLE data_table 
    (
     value  CHAR(80), 
     state BOOL 
    ) 
    """) 
#with database 
for i, x in enumerate(data): # i is index, x is data[i] 
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself 
     for c in range(s/x + 1): 
      cursor.execute(""" SELECT value, state FROM data_table WHERE value='%s' """ % ([s - c * x, i])) 
      if cursor.rowcount == 0: 
       #print 'nothing found, adding' 
       cursor.execute (""" INSERT INTO data_table (value, state) VALUES ('%s', False)""" % ([s - c * x, i])) 
      elif cursor.rowcount == 1: 
       cursor.execute (""" UPDATE data_table SET state=True WHERE value = '%s'""" % ([s - c * x, i])) 
       #print 'record updated' 
    conn.commit() 

#False is 17 and True is 286. Total is: 303 

ちょうど(あなたがコードを実行したくない場合には)それをまとめるために、defaultdictはこの中に何かが照会され、偽のエントリを(作成:

は、ここに問題がある、私の変更されたコードですケースif T[s - c * x, i]:)この機能を複製するには値のmysql検索を行い、それが存在しない場合は作成し、存在する場合はtrueに設定します。機能を正確に再現できないのではないでしょうか。

私が考えていた唯一のもう一つの点は、結果が(222, 0) : Falseと表示されていますが、mysqlは[222,0]

答えて

1

あなたの2つの例では、同じキーを更新されていません。

# First example 
if T[s - c * x, i]: 
    T[s, i+1] = True 
    # Key is (s, i+1) 

# Second example 
elif cursor.rowcount == 1: 
    cursor.execute (""" UPDATE data_table SET state=True WHERE value = '%s'""" % ([s - c * x, i])) 
    # Key is (s - c * x, i) 

IMOそれはちょうどあなたのプログラムが簡素になるかもしれない、データベース内の真の例を、保存するために、より理にかなって。それ以外の場合は、データベースに(s, i+1)が存在するかどうかを確認し、Trueの場合は更新し、そうでない場合は新しい行を作成する必要があります。

P.S.私はまた、(0, 0)をTrueに設定したコマンドを逃しました。あなたはあなたのデータベースを作成した直後に挿入物にすべきではありませんか?

更新は:selectコマンドだけで、その値が何であるか、行が存在するかどうかをチェックしません。また、あなたのコード内の別の問題が見つかりました。最初の例を正しく複製するには、コードは次のようにする必要があります。

cursor.execute (""" INSERT INTO data_table (value, state) VALUES ('%s', True)""" % ([0, 0])) 
conn.commit() 
# Inserted the (0,0) case 
for i, x in enumerate(data): 
    for s in range(target_sum + 1): 
     for c in range(s/x + 1): 
      cursor.execute(""" SELECT value, state FROM data_table WHERE value='%s' """ % ([s - c * x, i])) 
      if cursor.rowcount == 0: 
       cursor.execute (""" INSERT INTO data_table (value, state) VALUES ('%s', False)""" % ([s - c * x, i])) 
      elif cursor.rowcount == 1: 
       (value, state) = cursor.fetchone() # Gets the state 
       if state: # equivalent to your if in the first example 
        insertOrUpdate(conn, [s, i+1]) 
    conn.commit() 

変更された行がコメント化されています。

更新2:これでは十分ではありませんでした(私が言ったように、真の値を保存した方がずっと簡単です)。読みやすくするために、ここでif内の一部を移動:

def insertOrUpdate(conn, key): 
    cursor.execute(""" SELECT value, state FROM data_table WHERE value='%s' """ % key) 
     if cursor.rowcount == 0: 
      # Insert as True if not exists 
      cursor.execute (""" INSERT INTO data_table (value, state) VALUES ('%s', True)""" % key) 
     elif cursor.rowcount == 1: 
      (value, state) = cursor.fetchone() 
      if !state: 
       # Update as True, if it was False 
       cursor.execute (""" UPDATE data_table SET state=True WHERE value = '%s'""" % key) 

をアップデート3:ただプログラムだけで真の値を格納することによって簡単になるだろうか見て、対比します。また、ディスクスペースを節約し、時間を短縮し、defaultdictのように動作します。

cursor = conn.cursor() 
cursor.execute ("DROP TABLE IF EXISTS data_table") 
cursor.execute (""" 
    CREATE TABLE data_table(
     value  CHAR(80) 
    ) 
""") 

cursor.execute (""" INSERT INTO data_table (value) VALUES ('%s')""" % [0, 0]) 
conn.commit() 

for i, x in enumerate(data): # i is index, x is data[i] 
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself 
     for c in range(s/x + 1): 
      cursor.execute(""" SELECT value FROM data_table WHERE value='%s' """ % ([s - c * x, i])) 
      if cursor.rowcount == 1: 
       cursor.execute(""" SELECT value FROM data_table WHERE value='%s' """ % [s, i+1]) 
       if cursor.rowcount == 0: 
        cursor.execute (""" INSERT INTO data_table (value) VALUES ('%s')""" % [s, i+1]) 
    conn.commit() 
+0

これを指摘していただきありがとうございます。私はそれを修正しました。今はすべてが偽です。しかし、アルゴは、過去の要求を見て、それが以前に作られた場合は値を変更することによって動作します。 – Lostsoul

+0

@Lostsoul私の更新された答えをチェックしてください。そのエラーは唯一のものではありません。 – mgibsonbr

+0

@Lostsoul私はまた、真の値 – mgibsonbr

関連する問題