【问题标题】:multiple keys in dict that are the same and are tuplesdict 中的多个键相同且是元组
【发布时间】:2015-04-07 06:04:35
【问题描述】:

我有一组坐标(在作为原点的元组中)要附加到字典中,然后是另一个元组(端点)。

{(0, 0, 0):(10, 10, 10)}

有可能会将多个相同的原点坐标放入字典中,然后是不同的端点。

如果我尝试这个,它们会覆盖,这就是为什么我厌倦了 here 中存在可变对象的方法。唯一的问题是,如果我尝试从中获取 x、y 和 z,结果证明该对象不可迭代。

有人可以从那里修复代码(将在下面发布我正在做的事情)或给我一个更好的方法吗?谢谢。 (对于可变对象还是新手)

代码:

class coords(object):
    def __init__(self,part): 
        self.part = part
    def __str__(self):
        return 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 = k
    print x,y,z

#Here I get the error: "TypeError: 'coords' object is not iterable" at the line "x, y, z = k"

【问题讨论】:

  • 为什么不将初始点的字典存储到目标目的地集? {(0, 0, 0):{(10, 10, 10), (2,1,6) 等}}。每当您最初添加点时,请创建一个空集。然后将每个目标目的地添加到集合中。 (一个 defaultdict 也可以简化一些代码)。
  • 为什么不直接做x, y, z = str(k)...或k.part
  • @Lalaland 这是一个很好的方法,我之前实际上尝试过这种方法(只是作为一个列表),但我遇到了一些麻烦,但我成功了,谢谢!

标签: python dictionary


【解决方案1】:

您可以使用元组子类,它在平等方面的行为与标准元组不同。

class htuple(tuple):
  def __hash__(self):
    return id(self)
  def __eq__(self, other):
    return self is other

现在您可以像这样创建htuples:htuple((1,2,3))

这些htuples 的行为有点像lists(它们仅在身份上相等)和最像tuples(可以用作字典键,可以迭代等):

{ htuple((1,2,3)): (4,5,6),
  htuple((1,2,3)): (7,8,9) }

这是一个hack(我不能强调这一点)。但也许在您的特殊情况下,这是您可以接受的解决方案。

【讨论】:

  • 如果他真的要使用字典,这绝对是正确的解决方案。
  • @Linuxios 是的,然后只有。 dict 背后的主要思想(能够用值对其进行索引)在这里被禁用,因为您只能使用值来索引自身产生的dict(可能使用keys() 或@987654331 @ 或类似)。在大多数情况下,使用这些元组的元组列表(您的解决方案)要干净得多。
  • @Alfe:谢谢。不过,对于提出这个问题的其他人来说,我们有两种方法是很好的。
  • @Linuxios 它会咬你的。编码应该更像科学,而不是炼金术。我认为你应该改变你的模型,而不是绕过语言让它现在可以工作。这会改变语义,因此您的语法可以正常工作。 IMO这是XY问题。我认为您正在寻找多值字典。好吧,你被作者警告了。
  • @luk32:但是,您是对的,并且可能应该将该评论提交给 OP。黑客有自己的位置,主要是在维护无法更改的内容方面,但从长远来看,将数据结构更改为更自然总是对您有所帮助。
【解决方案2】:

获得所需内容的最简单方法是使用 2 元组端点列表:

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)

【讨论】:

    【解决方案3】:

    您可能需要从 str 中返回一个字符串而不是元组。然后在循环中只需使用从 coords str 方法返回的键调用字典。

    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
    

    【讨论】:

      【解决方案4】:

      我参加聚会有点晚了,但我认为这个解决方案应该摆在桌面上。解决在哈希表中的任何给定键处具有多个值的经典(尽管非常基本)方法是使用列表结构来枚举具有冲突键的所有值。最好的部分是你可以使用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,等等....

      【讨论】:

      • 听起来很像 Lalaland 在问题下方的评论 ;-) 添加关于使用 defaultdict 的部分(这可能是最好的解决方案),你可能会得到我的支持 :)跨度>
      • Alfe 是正确的,这基本上是 Lalaland 的解决方案(我没有阅读 cmets -- 哎呀!)。我仍然保留它,以便解决方案在解决方案列表中表示。 @Lalaland,如果你想写一个答案,我会把它记下来。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多