Python 正在尝试从字典列表中的列表中删除特定项。(蟒蛇2)
我的数据结构如下:Python 正在尝试从字典列表中的列表中删除特定项。(蟒蛇2),python,list,dictionary,Python,List,Dictionary,我的数据结构如下: def cross(A, B): return [a+b for a in A for b in B] digits = '123456789' rows = 'ABCDEFGHI' cols = digits squares = cross(rows, cols) unitlist = ([cross(rows, c) for c in cols] + [cross(r, cols) for r in rows] +
def cross(A, B):
return [a+b for a in A for b in B]
digits = '123456789'
rows = 'ABCDEFGHI'
cols = digits
squares = cross(rows, cols)
unitlist = ([cross(rows, c) for c in cols] +
[cross(r, cols) for r in rows] +
[cross(rs, cs) for rs in ('ABC', 'DEF', 'GHI') for cs in ('123', '456', '789')])
units = dict((s, [u for u in unitlist if s in u]) for s in squares)
peers = dict((s, set(sum(units[s],[]))-set([s])) for s in squares)
这会导致单位输出
{'A1': [['A1','A2','A3','A4','A5','A6','A7','A8','A9'],
['A1','B1','C1','D1','E1','F1','G1','H1','I1'],
['A1','A2','A3','B1','B2','B3','C1','C2','C3']],
'A2': [['A1','A2','A3','A4','A5','A6','A7','A8','A9'],
['A2','B2','C2','D2','E2','F2','G2','H2','I2'],
['A1','A2','A3','B1','B2','B3','C1','C2','C3']],
'A3': [[etc.]]}
我希望能够创建单位的副本,但不希望键是它自己列表中的字符串。因此,我希望从前3个列表中删除“A1”A2'从接下来的3个列表中删除,等等
我可以导入副本并执行units2=copy.deepcopy(units)
然后执行units2['A1'][0]。删除('A1')
一次执行一个列表。所以我试着做一个循环,一次完成这一切
for s in squares: #assign s to 'A1' then 'A2', etc.
for x in range(3): #
units2[s][x].remove(s)
我认为这可以通过跑步完美地完成
units2['A1'][0].remove('A1')
units2['A1'][1].remove('A1')
units2['A1'][2].remove('A1')
units2['A2'][0].remove('A2')
# etc.
不幸的是,在运行此循环后,我的结果是:
units2 = {'B8': [[], [], []],
'H1': [[], [], []],
'C7': [[], [], []],
'B3': [[], [], []],
# etc.
}
因此,不知何故,这个循环正在删除列表中的所有数据,而不仅仅是当前[x]列表中的当前[s]
我尝试过以不同的方式构建列表,甚至制作了81个版本的
for x in range(3):
units2['A1'][x].remove('A1')
for x in range(3):
units2['A2'][x].remove('A2')
for x in range(3):
units2['A3'][x].remove('A3')
但我的字典值都是空的
*我想做的是构建一个数独解算器,然后在PyGame中为游戏生成数独。我计划使用
units2
中的列表来检查是否任何给定列表中只有1个单元格仍然符合特定数字的条件。如果是这种情况,我知道该单元格必须将该数字作为其值,因为它是列、行或9x9块中唯一一个可以根据规则合法保存它的单元格。使用嵌套列表将单位更改为:
units = dict((s, [[e for e in u if s != e]
for u in unitlist if s in u]) for s in squares)
如果你看看这里发生了什么,然后退一步,答案就显而易见了 毫无疑问,您知道这是什么原因造成的:
In [1]: a = [1,2,3]
In [2]: b = a
In [3]: a.remove(2)
In [4]: print(a)
[1, 3]
In [5]: print(b)
[1, 3]
这就是为什么您有copy.deepcopy
。但是,当您查看正在发生的事情时,如果您使用,很明显的答案是您对同一列表有多个引用,并且当您从另一个列表中删除时,最终清空了结构中的所有列表。这里有一个简单的方法来检查:
import collections
import pprint
counter = collections.Counter()
for s in squares:
for x in range(3):
counter[id(units2[s][x])] += 1
pprint.pprint(counter)
哪些输出(毫不奇怪):
显然,您的id
s会有所不同,但计数都是9
您还可以在循环时使用或检查变量
如果将单位2
替换为单位
,则会得到相同的计数。所以这里真正的问题是,为什么不按您认为的方式复制.deepcopy呢?为什么在列表列表中有同一列表的多个副本
让我们尝试一些实验:
list_of_lists = [[1,1,1],
[2,2,2],
[3,3,3],
]
deepcopy_of_lists = copy.deepcopy(list_of_lists)
print(id(list_of_lists))
print(id(deepcopy_of_lists))
我希望这里有两个不同的id,事实上他们是。但是它们的内容呢
print(id(list_of_lists[0]))
print(id(deepcopy_of_lists[0]))
是的。这些是不同的。如果我们把这些放在字典里呢
dict_of_list_of_lists = {'list_of_lists': list_of_lists}
deepcopy_of_dict = copy.deepcopy(dict_of_list_of_lists)
print(id(dict_of_list_of_lists['list_of_lists'][0]))
print(id(deepcopy_of_dict['list_of_lists'][0]))
我们仍然得到不同的id
s。一切似乎都在按预期进行,所以很明显我们遗漏了一些东西。哦,是的,我们正在比较复制的列表和原始列表
如果将单位2
替换为单位
,则会得到相同的计数
有一个暗示。此外,如果您阅读以下内容:
深度复制操作通常存在两个问题,而浅层复制操作则不存在这两个问题:
- 递归对象(直接或间接包含自身引用的复合对象)可能导致递归循环
- 因为深度复制会复制所有内容,所以它可能会复制太多内容,例如,即使在副本之间也应该共享的管理数据结构
- 保存当前复制过程中已复制对象的“备忘录”字典;及
- 允许用户定义的类重写复制操作或复制的组件集
deepcopy
关注它已经看到的对象
瞧!我们找到了罪魁祸首
在原始词典units
中,同一列表中有多个不同键的副本。这是因为这一行:
units = dict((s, [u for u in unitlist if s in u]) for s in squares)
本节特别强调:
[u for u in unitlist if s in u]
您在整个词典中重复引用unitlist
中的列表。幸运的是,这是一个微不足道的修复:
[u[:] for u in unitlist if s in u]
每次都将复制该列表,其余代码将正常工作
import pprint
import copy
import pprint
def cross(A, B):
return [a+b for a in A for b in B]
digits = '123456789'
rows = 'ABCDEFGHI'
cols = digits
squares = cross(rows, cols)
unitlist = ([cross(rows, c) for c in cols] +
[cross(r, cols) for r in rows] +
[cross(rs, cs) for rs in ('ABC', 'DEF', 'GHI') for cs in ('123', '456', '789')])
units = dict((s, [u[:] for u in unitlist if s in u]) for s in squares)
peers = dict((s, set(sum(units[s],[]))-set([s])) for s in squares)
units2 = copy.deepcopy(units)
for s in squares: #assign s to 'A1' then 'A2', etc.
for x in range(3): #
units2[s][x].remove(s)
pprint.pprint(units2)
产出:
{'A1': [['B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
['A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']],
'A2': [['B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'],
['A1', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A1', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']],
'A3': [['B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'],
['A1', 'A2', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A1', 'A2', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']],
# and so on and so forth
}
什么是交叉函数?
import pprint
import copy
import pprint
def cross(A, B):
return [a+b for a in A for b in B]
digits = '123456789'
rows = 'ABCDEFGHI'
cols = digits
squares = cross(rows, cols)
unitlist = ([cross(rows, c) for c in cols] +
[cross(r, cols) for r in rows] +
[cross(rs, cs) for rs in ('ABC', 'DEF', 'GHI') for cs in ('123', '456', '789')])
units = dict((s, [u[:] for u in unitlist if s in u]) for s in squares)
peers = dict((s, set(sum(units[s],[]))-set([s])) for s in squares)
units2 = copy.deepcopy(units)
for s in squares: #assign s to 'A1' then 'A2', etc.
for x in range(3): #
units2[s][x].remove(s)
pprint.pprint(units2)
{'A1': [['B1', 'C1', 'D1', 'E1', 'F1', 'G1', 'H1', 'I1'],
['A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']],
'A2': [['B2', 'C2', 'D2', 'E2', 'F2', 'G2', 'H2', 'I2'],
['A1', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A1', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']],
'A3': [['B3', 'C3', 'D3', 'E3', 'F3', 'G3', 'H3', 'I3'],
['A1', 'A2', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'],
['A1', 'A2', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']],
# and so on and so forth
}