Python dict中有多个相同且为元组的键
我有一组坐标(以元组为原点),我将其添加到字典中,然后是另一个元组(端点) 原点的同一坐标的倍数可能会被放入dict中,然后是不同的端点 如果我尝试这样做,它们将覆盖,这就是为什么我已经厌倦了存在可变对象的方法。唯一的问题是,如果我试着从中得到x,y和z,结果证明这个对象是不可迭代的 有人可以从那里修复代码(将在下面发布我正在做的事情)或给我一个更好的方法来做这件事吗?谢谢(对于可变对象仍然是新的) 代码:Python dict中有多个相同且为元组的键,python,dictionary,Python,Dictionary,我有一组坐标(以元组为原点),我将其添加到字典中,然后是另一个元组(端点) 原点的同一坐标的倍数可能会被放入dict中,然后是不同的端点 如果我尝试这样做,它们将覆盖,这就是为什么我已经厌倦了存在可变对象的方法。唯一的问题是,如果我试着从中得到x,y和z,结果证明这个对象是不可迭代的 有人可以从那里修复代码(将在下面发布我正在做的事情)或给我一个更好的方法来做这件事吗?谢谢(对于可变对象仍然是新的) 代码: 您可能需要从str返回字符串,而不是元组。然后在循环中,只需使用从coordsstr方法
您可能需要从str返回字符串,而不是元组。然后在循环中,只需使用从coordsstr方法返回的键调用字典即可
class coords(object):
def __init__(self,part):
self.part = part
def __str__(self):
return str(self.part)
d = {}
d[coords((0, 10, 0))] = (0 ,0 ,0)
d[coords((0, 10, 0))] = (0 ,1 ,0)
d[coords((0, 10, 0))] = (0 ,2 ,0)
for k in d:
x, y, z = d[k]
print x,y,z
您可以使用一个元组子类,它与标准元组具有不同的关于相等性的行为
class htuple(tuple):
def __hash__(self):
return id(self)
def __eq__(self, other):
return self is other
现在您可以像这样创建htuple
s:htuple((1,2,3))
这些htuple
s的行为有点像list
s(它们仅在标识上相等)和一个非常像tuple
s(可以用作字典键,可以迭代,等等):
这是一个黑客行为(我再怎么强调也不为过)。但也许在您的特殊情况下,这是一种您可以接受的解决方案。获得所需的最简单的方法是使用一个包含两个端点元组的列表:
endpoint_tuples = [((0, 0, 0), (1, 1, 1)), ((2, 3, 4), (5, 6, 7))]
for start_point, end_point in endpoint_tuples:
print start_point
print end_point
如果需要查找某个起点的端点p
:
next(endpoints for endpoints in endpoint_tuples if endpoints[0] == p)
我参加聚会有点晚了,但我认为这个解决办法应该摆在桌面上。解决哈希表中任意给定键处有多个值的问题的一种经典(尽管是非常基本的)方法是使用列表结构枚举具有冲突键的所有值。最好的一点是,您可以使用
defaultdict
类型,而不需要任何游戏/技巧
d = {}
values = [
(coords((0, 10, 0)), (0, 0, 0)),
(coords((0, 10, 0)), (0, 1, 0)),
(coords((0, 10, 0)), (0, 2, 0)),
]
for start, end in values:
if start not in d:
d[start] = []
d[start].append(end)
for start in d:
for end in d[start]:
x, y, z = end
print x,y,z
对我来说,这比@Alfe的解决方案要少得多,该解决方案包含多个看似匹配的哈希键,并且仍然允许您将dict用作正确的dict(否则,有什么意义?)
另外,您不需要使用列表来存储多个值,我只是使用列表,因为它很简单/明显。您可以使用一个集合类型(用于自动重复数据消除),或者如果您认为您可以使用辅助哈希算法(如果您将有很多冲突),则可以使用另一个dict,等等……为什么不将初始点dict存储到目标目的地集合?{(0,0,0):{(10,10,10),(2,1,6)等}。无论何时开始添加点,都要创建一个空集。然后将每个目标目的地添加到集合中。(一个defaultdict也可以简化一些代码)。为什么不直接做
x,y,z=str(k)
…或k.part
@lalalaland这是一个很好的方法,我以前确实尝试过这种方法(只是作为列表),但我遇到了一些麻烦,但我成功了,谢谢!如果他真的需要使用字典,这绝对是正确的解决方案。@Linuxios是的,只有这样。dict
(能够用一个值对其进行索引)背后的主要思想在这里被禁用了,因为您只能使用值来对来自自身的dict
进行索引(可能使用keys()
或iteritems()
或类似方法)。在大多数情况下,使用这些元组中的一个元组列表(您的解决方案)会更简洁。@Alfe:谢谢。很好,我们有两种方法来解决任何其他人的问题。@Linuxios它会咬你的。编码应该更像科学,而不是炼金术。我认为你应该改变你的模型,而不是为了让它暂时工作而对语言进行修改。这会更改语义,以便语法正常工作。在我看来,这是个问题。我想你在找多值词典。嗯,作者已经警告过你。@luk32:不过,你是对的,可能应该把这句话写在OP上。黑客有自己的位置,主要是维护那些无法改变的东西,但是,从长远来看,将数据结构更改为更自然的数据结构将始终对您有所帮助添加一个关于使用defaultdict
(这可能是最好的解决方案)的部分,您可能会得到我的支持:)Alfe是正确的,这基本上是Lalaland的解决方案(我没有阅读注释--哎呀!)。我仍然保留它,以便在解决方案列表中表示该解决方案@拉拉兰,如果你想找个时间写个答案,我会记下来的。
endpoint_tuples = [((0, 0, 0), (1, 1, 1)), ((2, 3, 4), (5, 6, 7))]
for start_point, end_point in endpoint_tuples:
print start_point
print end_point
next(endpoints for endpoints in endpoint_tuples if endpoints[0] == p)
d = {}
values = [
(coords((0, 10, 0)), (0, 0, 0)),
(coords((0, 10, 0)), (0, 1, 0)),
(coords((0, 10, 0)), (0, 2, 0)),
]
for start, end in values:
if start not in d:
d[start] = []
d[start].append(end)
for start in d:
for end in d[start]:
x, y, z = end
print x,y,z