【问题标题】:Python complex dictionary keysPython 复杂的字典键
【发布时间】:2012-11-11 11:07:45
【问题描述】:

我的问题与字典键有关。我想为任何单个对象设置一个包含 3 个键的字典。键必须按顺序排列,并且可以具有广泛的值。例如,

dictionary = {(key1,key2,key3) : object}

key1 可以是 1 到 10 之间的任何值 key2 可以是 11 到 20 之间的任何值 key3 可以是 21 到 30 之间的任何值

放置键的顺序很重要。

更具体地说,我的键对应于 x,y,z 笛卡尔坐标的范围,许多对象在其中浮动。我希望能够根据对象的 x,y,z 对对象的相对位置进行排序职位。

有什么方法可以设置,还是我必须采取不同的方法? 谢谢你的帮助!

【问题讨论】:

  • 我认为应该是可能的。你为什么不试试呢?
  • 看起来你的例子是你应该尝试的。只需将元组作为键
  • 请注意字典实际上是您想要的,因为这意味着没有两个对象可以具有完全相同的 xyz 位置(因为每个键只包含一个值)。如果您有一个包含 x、y 和 z 字段的对象列表,则可以将其排序为 sortedByZ = sorted(objects, key = lambda obj: obj.z)
  • “x,y,z 笛卡尔坐标的范围”是如何定义的?是某种舍入来定义哪些点相等吗?我建议您在将坐标值放入元组以用作键之前“标准化”(例如四舍五入)您的坐标值。然后,当你想取回它时,做同样的事情,标准化可能略有不同的坐标以获得相同的键。

标签: python dictionary key


【解决方案1】:

当然可以,也可以为此创建单个字符串键 - 只需为您的键合并字符串结果,例如 ','.join([k1,k2,k3])

Read more about dictionaries.

字典由键索引,可以是任何不可变类型; 字符串和数字总是可以作为键。元组可以用作键,如果 它们只包含字符串、数字或元组;如果一个元组包含任何 直接或间接的可变对象,它不能用作 钥匙。您不能将列表用作键,因为可以就地修改列表 使用索引分配、切片分配或 append() 之类的方法 和扩展()。

所以你尝试使用元组作为键,这没关系。

请注意,python 中的字典没有排序。您可以为此使用 collections.OrderedDict。此外,要建立正确的排序,请使用 sort/sorted functions 并指定参数键以按照您想要的方式进行排序。

编辑样本:

from itertools import product
myDict = {}
for x,y,z in product(range(10), range(10,20), range(20,30)):
    myDict[(x,y,z)] = sum([x,y,z])

【讨论】:

  • 好的,这很有帮助。这可以解决订单问题。但我想使用对象 x,y,z 坐标作为访问存储在我的字典中的另一种不同类型对象的关键。我不确定如何启用每个键都可以接受的范围广泛的值。这有意义吗?
  • @user1846529 您需要向我们提供一个按键输入示例以及您需要什么 - 对我来说,您所说的一切看起来都不错,应该可以使用
  • 我的密钥看起来像这样 (1.8,12.3,24.9),并且密钥的每个部分都必须有一个可以接受的值范围。所以 (1,12,24) 也可以满足键的条件,或者 (2,13,25) 也可以工作......
  • @user1846529 正如我所说,python 允许你使用元组作为字典键,它包含浮点值是可以的,你有什么真正的问题 - 找到什么?
  • @user1846529,python 是动态类型的。您不需要指定键的范围。你只需分配他们d[(1.1,2.2,3.3)] = MyObject()
【解决方案2】:

希望你会发现这很有用。

>>> from math import sqrt
>>> def dist(p1, p2):
...     x1, y1, z1 = p1
...     x2, y2, z2 = p2
...     xd = x1 - x2
...     yd = y1 - y2
...     zd = z1 - z2
...     return sqrt((xd ** 2 + yd ** 2 + zd ** 2))
>>> myPoint = (0,0,0)
>>> class MyObject: pass
>>> myDict = {(1,2,3):MyObject(), (4,5,6):MyObject()}
>>> sorted([dist(myPoint, point) for point in myDict])
10: [3.7416573867739413, 8.774964387392123]

【讨论】:

    【解决方案3】:

    在我看来,您想要一个从键(有序三元组)到值(对象)的映射的可能无序集合。如果是这种情况,很容易从有序三元组中生成复合键:

    假设obj0 位于x,y,z 坐标(10,20,30) 并且obj1 位于x,y,z 坐标(11,21,31)。那么:

    myObjects = {(10,20,30): obj0,
                 (11,21,31): obj1
                }
    

    这是因为tuples 和ints 都是不可变类型

    希望有帮助

    【讨论】:

    • 这很接近,但是我希望对象接受键的每个部分的广泛值。例如,密钥的第一部分可以接受从 1 到 100 的任何值,第二部分可以接受从 100 到 200 的任何值。我不知道该怎么做......
    • 你可以很容易地做到{(101,208,35): obj1}。您是否正在寻找可以在插入新密钥时检查范围的东西?
    • 当我插入一个新键时,我希望字典知道插入的值在与字典中存储的对象相对应的特定范围内。
    • 只是为了确保我做对了:当你将一个对象(以它的 xyz 坐标作为键)插入到字典中时,你要确保它的 xyz 坐标在一定范围内。该范围将由字典中已经存在的另一个对象的 xyz 坐标确定。它是否正确?聊聊规范in this chatroom
    • 我的字典中存储的对象是具有 x、y、z 最小值和最大值的框。我希望 x,y,z 的最小值和最大值之间的范围是关键。所以我有其他物体在空间中随机漂浮,我想将它们的 x、y、z 位置插入到键中,这样我就知道它们包含在哪个盒子中。希望这更有意义。
    【解决方案4】:

    我解决了这个问题:

    list = [
             [1,'a','school'],
             [2,'b','church'],
             [3,'c','library'],
             [4,'d','station']
        ]
    dic_key = {}
    for i in list:
       if (i[0],i[1]) not in dic_key:
          dic_key[i[0],i[1]] = []
       dic_key[i[0],i[1]].append(i[2])
    
    print(dic_key)
    

    输出:{(1, 'a'): ['school'], (2, 'b'): ['church'], (3, 'c'): ['library'], (4 , 'd'): ['站']}

    【讨论】:

      猜你喜欢
      • 2013-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 2017-04-06
      • 1970-01-01
      相关资源
      最近更新 更多