Результаты разные для Python и MySQL для аналогичной команды
Я использовал python для создания словаря, но по мере того, как мои данные увеличивались, у меня возникали ошибки памяти, поэтому я решил сэкономить память и просто записать данные в базу данных, но результаты не совпадают. Я думаю, что это связано с поведением defaultdict (но я не уверен).
Вот рабочий код 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. Я очень подозреваю, что не могу правильно воспроизвести функциональность
Единственное, о чем я думал, это то, что 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, если он есть, создайте новую строку, если это не так.
PS Я также пропустил команду, где вы установили (0, 0)
к Истине. Разве это не должно быть во вставке, сразу после того, как вы создали свою базу данных?
Обновление: также обнаружил еще одну проблему в вашем коде: команда выбора просто проверяет, существует ли строка, а не ее значение. Чтобы правильно повторить ваш первый пример, ваш код должен быть:
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: для сравнения, посмотрите, как программа будет проще, просто сохраняя значения True. Он также использует меньше дискового пространства, занимает меньше времени и ведет себя больше как 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()