2012-02-17 42 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 

結果是值的大表(你可以看到在評論擊穿這是正確的結果我想要),但是當我將第一條語句的最後一行更改爲添加到數據庫而不是本地字典時,結果會有所不同。

這裏是我修改後的代碼是有問題的:

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創建時的東西被查詢的虛假條目(在此case if T[s - c * x, i]:)所以要複製這個特性,我做了一個mysql查找值,如果它不存在,那麼我創建它,如果它確實存在,那麼我將它設置爲true。我高度懷疑我沒有正確地複製功能

我唯一想到的其他事情是python顯示結果爲(222, 0) : False但mysql正在做[222,0]不知道這是否有所作爲。

回答

1

你的兩個例子都沒有更新相同的密鑰:

# 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的命令。在創建數據庫之後,不應該插入插入內容嗎?

更新:還發現,在你的代碼中的另一個問題:選擇命令只檢查一列是否存在,它的價值是不是有什麼。要正確地複製您的第一個示例,您的代碼應該是:

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 2012-02-17 23:39:09

+0

@Lostsoul檢查我的更新答案,那個錯誤不是唯一的。 – mgibsonbr 2012-02-17 23:51:01

+0

@Lostsoul我也發佈了一個替代解決方案,只存儲True值 – mgibsonbr 2012-02-18 00:13:40