如何防止将相同的值(使用另一个键)添加到字典中?
How can I prevent adding the same value (With another key) into a dictionary?
我需要用下一个代码给出的键值对填充字典:
for i in range(1,n+1):
d = {}
Ri = Vector([#SomeCoordinates])
for k in range(1,n+1):
Rk = Vector([#SomeCoordinates])
if i != k:
d['R'+str(i)+str(k)] = (Rk-Ri).mod # Distance between Ri and Rk
else:
None
""" Since (Rk-Ri).mod gives me the distance between two points (i and k),
it's meaningless to calc the distance if i == k. """
这是问题所在:
'Rik' 表示与 'Rki' 相同的距离,我不想添加两次距离。
然后,我尝试使用此代码:
if i != k and ( ('R'+str(i)+str(k)) and ('R'+str(k)+str(i)) ) not in d:
d['R'+str(i)+str(k)] = (Rk-Ri).mod
else:
None
但问题依然存在。
当我 "print d" 我得到 R12 和 R21(每对数字“ i k ”也是如此)。
我能做什么?
您可以始终将较小的值放在前面,以便自动覆盖之前的条目:
if i != k:
key = str(i) + "," + str(k) if i < k else str(k) + "," + str(i)
d['R'+key] = (Rk-Ri).mod
(我假设您的脚本只需要距离值,而不需要来自当前键的信息。)
您可以使用以下内容:
d = {}
for i in range(1, n + 1):
Ri = Vector([#SomeCoordinates]).
for k in range(i + 1, n + 1):
Rk = Vector([#SomeCoordinates])
d[i, k] = d[k, i] = (Rk - Ri).mod
通过这种方式,我们确保只取一对(通过强制执行 k > i
),然后我们可以将 (i, k)
和 (k, i)
的距离分配给字典。
我使用d[i, k]
而不是d['R' + str(i) + str(k)]
,因为后者有以下缺点:我们无法推断,例如,如果d['R123']
指的是(12, 3)
或(1, 23)
.
此外,我将字典初始化 (d = {}
) 移到了两个循环之外,因为它是为每个 i
.
初始化的
如果我没理解错的话,你正在寻找两个元素的所有组合。您可以使用 itertools.combinations
自动生成所有此类组合,不重复。
d = {}
for i, k in itertools.combinations(range(1, n+1), 2):
Ri = Vector([SomeCoordinates])
Rk = Vector([SomeCoordinates])
d['R'+str(i)+str(k)] = (Rk-Ri).mod
你甚至可以把它变成一个字典理解(虽然它可能有点长):
d = {'R'+str(i)+str(k)] : (Vector([SomeCoordinates]) - Vector([SomeCoordinates])).mod
for i, k in itertools.combinations(range(1, n+1), 2)}
或者,要对 i
或 k
的每个值进行一次(可能很昂贵的)Vector([SomeCoordinates])
计算,试试这个(感谢 JuniorCompressor 指出这一点):
R = {i: Vector([SomeCoordinates]) for i in range(1, n+1)}
d = {(i, k): (R[i] - R[k]).mod for i, k in itertools.combinations(range(1, n+1), 2)}
此外,正如其他人指出的那样,'R'+str(i)+str(k)
不是一个好的密钥,因为无法区分例如(1,23)
和 (12,3)
,因为两者最终都是 'R123'
。我建议您只使用元组 (i,k)
代替。
我需要用下一个代码给出的键值对填充字典:
for i in range(1,n+1):
d = {}
Ri = Vector([#SomeCoordinates])
for k in range(1,n+1):
Rk = Vector([#SomeCoordinates])
if i != k:
d['R'+str(i)+str(k)] = (Rk-Ri).mod # Distance between Ri and Rk
else:
None
""" Since (Rk-Ri).mod gives me the distance between two points (i and k),
it's meaningless to calc the distance if i == k. """
这是问题所在:
'Rik' 表示与 'Rki' 相同的距离,我不想添加两次距离。
然后,我尝试使用此代码:
if i != k and ( ('R'+str(i)+str(k)) and ('R'+str(k)+str(i)) ) not in d:
d['R'+str(i)+str(k)] = (Rk-Ri).mod
else:
None
但问题依然存在。
当我 "print d" 我得到 R12 和 R21(每对数字“ i k ”也是如此)。
我能做什么?
您可以始终将较小的值放在前面,以便自动覆盖之前的条目:
if i != k:
key = str(i) + "," + str(k) if i < k else str(k) + "," + str(i)
d['R'+key] = (Rk-Ri).mod
(我假设您的脚本只需要距离值,而不需要来自当前键的信息。)
您可以使用以下内容:
d = {}
for i in range(1, n + 1):
Ri = Vector([#SomeCoordinates]).
for k in range(i + 1, n + 1):
Rk = Vector([#SomeCoordinates])
d[i, k] = d[k, i] = (Rk - Ri).mod
通过这种方式,我们确保只取一对(通过强制执行 k > i
),然后我们可以将 (i, k)
和 (k, i)
的距离分配给字典。
我使用d[i, k]
而不是d['R' + str(i) + str(k)]
,因为后者有以下缺点:我们无法推断,例如,如果d['R123']
指的是(12, 3)
或(1, 23)
.
此外,我将字典初始化 (d = {}
) 移到了两个循环之外,因为它是为每个 i
.
如果我没理解错的话,你正在寻找两个元素的所有组合。您可以使用 itertools.combinations
自动生成所有此类组合,不重复。
d = {}
for i, k in itertools.combinations(range(1, n+1), 2):
Ri = Vector([SomeCoordinates])
Rk = Vector([SomeCoordinates])
d['R'+str(i)+str(k)] = (Rk-Ri).mod
你甚至可以把它变成一个字典理解(虽然它可能有点长):
d = {'R'+str(i)+str(k)] : (Vector([SomeCoordinates]) - Vector([SomeCoordinates])).mod
for i, k in itertools.combinations(range(1, n+1), 2)}
或者,要对 i
或 k
的每个值进行一次(可能很昂贵的)Vector([SomeCoordinates])
计算,试试这个(感谢 JuniorCompressor 指出这一点):
R = {i: Vector([SomeCoordinates]) for i in range(1, n+1)}
d = {(i, k): (R[i] - R[k]).mod for i, k in itertools.combinations(range(1, n+1), 2)}
此外,正如其他人指出的那样,'R'+str(i)+str(k)
不是一个好的密钥,因为无法区分例如(1,23)
和 (12,3)
,因为两者最终都是 'R123'
。我建议您只使用元组 (i,k)
代替。