2012-09-09 39 views
0

我正在通过Project Euler编程,我遇到了一个奇怪的问题。我想找到所有可能的方法来从两个自然数中生成(自然)数字。我创建了一个简单的循环,我注意到了奇怪的结果。例如,从3和1产生1一些调查已经导致本:将值赋给python结果中的字典值为错误的键

#Importing stuff I often use in my solutions/tests 
from math import sqrt, log, floor, pow, fabs, factorial 
from sets import Set 
from random import randint 
from itertools import permutations 
import sys 


dub = dict() 

c = 0 #Counting the number of elements in dub[18], use to track changes 
for i in range (1,10): 
    if 18 in dub: #setting c = len(dub[18]) 
     c = len(dub[18]) 
    for j in range (i+1,10): 
     pair = [[i,j]] 
     v = i+j 
     if v in dub: 
      dub[v].append(pair[0]) 
     else: 
      dub[v] = pair 
     v = i*j   
     if v in dub: 
      dub[v].append(pair[0]) 
     else: 
      if i == 3 and j == 8: print 'here', v # The value that is added to dub[18] instead of dub[24] 
      dub[v] = pair 
     if 18 in dub and not c == len(dub[18]): #This is how I found that something is wrong. 
      c = len(dub[18]) 
      print dub[18] 
      print v,i,j 
      raw_input() 

与结果如下:

[[2, 9]] 
18 2 9 

[[2, 9], [3, 6]] 
18 3 6 

here 24 
[[2, 9], [3, 6], [3, 8]] 
24 3 8 

我应该使用的关键是24,但该列表放置在关键之下18.为什么这样?

回答

7

您正在重复使用多个键的相同列表。该行

pair = [[i,j]] 

创建一个包含单个对的列表。该列表在两个else分支

else: 
    dub[v] = pair 

导致两个不同的密钥使用同一列表对象使用。由于它是同一个对象,所以追加到列表中的任何一个都可以在另一个中看到。

编辑:这里有一个小例子,证明此行为:

>>> d = {} 
>>> a = [] 
>>> d[0] = a 
>>> d[1] = a 
>>> d[0].append(2) 
>>> d[0] 
[2] 
>>> d[1] 
[2] 

最明显的解决方法是只对指定的名称pair,并创建包含对一个新的列表需要的时候:

dub = {} 
for i in range (1, 10): 
    for j in range (i + 1, 10): 
     pair = [i, j] 
     v = i + j 
     if v in dub: 
      dub[v].append(pair) 
     else: 
      dub[v] = [pair] 
     v = i * j 
     if v in dub: 
      dub[v].append(pair) 
     else: 
      dub[v] = [pair] 

为了进一步简化该代码,您可以通过dict.setdefault()更换if S:

dub = {} 
for i in range (1, 10): 
    for j in range (i + 1, 10): 
     pair = [i, j] 
     dub.setdefault(i + j, []).append(pair) 
     dub.setdefault(i * j, []).append(pair) 
+0

您的解决方案的工作,但我还是不明白。我使用不同的键,但我追加到同一个列表中? – Yotam

+0

@Yam:我添加了一个有希望的解释性例子。 –

+0

@SvenMarmach:谢谢。我现在知道了。 – Yotam

0

如果使用fromkeys,也会导致此问题。

数据= dict.fromkeys([INT(X)为X [1行:]],[])

该溶液是用setdefault代替fromkeys启动的默认值字典:

data.setdefault(IDX,[])追加((行[0],VAL))