我有一个字典,提供从实数元组到标识整数的映射。给定一个包含数字的元组列表,这些数字在容差范围内,但完全等于字典中的容差,我想生成一个相应整数的列表。
示例:
tdict = {(0.334, 0.333, 0.333):1, (0.167, 0.666, 0.167):2, (0.5, 0.5, 0):3}
tlist = [(0.333, 0.333, 0.333), (0.16667, 0.6666667, 0.17), (0.34, 0.33, 0.33), (0.5001, 0.4999, 0.0)]
tol = 0.01
运行我想要的代码应该产生结果
ilist = [1,2,1,3]
因为每个元组中的所有数字都在tdict
中相应元组中的数字的给定容差范围内。我可以通过迭代tdict.keys()
并单独比较每个来做到这一点,但我觉得应该有更好的方法。获取相应整数到这些元组的最有效方法是什么?它不需要涉及字典,这对我来说似乎是最自然的。我正在使用Python 3。
答案 0 :(得分:6)
您显然希望在具有特定网格间距(与您的容差值直接相关)的3D网格上的3D空间中投影点,并创建某种直方图。给自己写一个投影函数:它将一个任意的3元素列表/元组(一个描述空间中的点的向量)作为参数,并将其投影到某个网格点上。你这样做是为了填写你的字典以及阅读它。此外,关于字典中的键,我认为你应该使用整数元组而不是浮点数,因为我不确定浮点数是否可以相同。
这是一个实现示例:
from collections import defaultdict
from random import random as rn
class Grid(object):
def __init__(self, spacing):
self.spacing = spacing
self.griddict = defaultdict(int)
def add_point(self, coords):
"""
`vid`, a voxel id, is a tuple of indices, indicating one grid
bin for each dimension, e.g. (1, 5, 2)
rule: i_x = int(floor(x_coord / spacing))
"""
vid = tuple([int(c//self.spacing) for c in coords])
self.griddict[vid] += 1
def get_point(self, coords):
vid = tuple([int(c//self.spacing) for c in coords])
return self.griddict[vid]
def vid_centercoords(self, vid):
"""
Return the real coordinates in space for a certain voxel,
which is identified by its voxel id `vid` (a tuple of indices).
"""
return tuple([(i-1)*self.spacing + self.spacing/2 for i in vid])
N = 20
fillpoints = [(rn(),rn(),rn()) for _ in xrange(N)]
testpoints = [(rn(),rn(),rn()) for _ in xrange(N)]
grid = Grid(spacing=0.3)
for p in fillpoints:
grid.add_point(p)
print [grid.get_point(p) for p in testpoints]
它的作用:它在3D空间中创建20个随机向量(所有坐标在0和1之间)。它使用空间中的这些点填充3D网格。网格在每个维度上的间距为0.3。空间中的这20个点中的每一个被分配给网格中的某个体素(仅用于3D像素的单词)。每个赋值将相应体素的计数器增加1(将网格渲染为直方图)。然后,使用另一组随机的20个向量来读出体素。这些点再次投射到体素上,但这次计数器只是返回而不是增加。执行测试:
$ python gridtest.py
[2, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]
使用您的数据执行:
fillpoints = [(0.334, 0.333, 0.333), (0.167, 0.666, 0.167), (0.167, 0.666, 0.167), (0.5, 0.5, 0), (0.5, 0.5, 0), (0.5, 0.5, 0)]
testpoints = [(0.333, 0.333, 0.333), (0.16667, 0.6666667, 0.17), (0.34, 0.33, 0.33), (0.5001, 0.4999, 0.0)]
grid = Grid(spacing=0.03)
for p in fillpoints:
grid.add_point(p)
print [grid.get_point(p) for p in testpoints]
根据需要打印[1, 2, 1, 3]
。我没有深入思考关系spacing=3*tolerance
。这可能是错的。我只知道存在确定性关系。证明/找到这个公式是为了练习:)
答案 1 :(得分:2)
tdict.keys()
按距离tlist
的每个点排序。tdict
中查找。答案 2 :(得分:2)
如果您有权访问numpy,可以使用numpy.allclose检查匹配项:
>>> import numpy
>>> numpy.allclose((0.334, 0.333, 0.333), (0.333, 0.333, 0.333))
False
>>> numpy.allclose((0.334, 0.333, 0.333), (0.333, 0.333, 0.333), atol=0.1)
True
答案 3 :(得分:1)
你可以查找功能(查找元组的圆形版本):
def look_up_tdict( t ):
return tdict[ (float('%.3f' % t[0]),
float('%.3f' % t[1]),
float('%.3f' % t[2])
]
注意:如果字典中的任何内容都不在t
附近,则会出错。然后您可以填充ilist
:
ilist = [ look_up_tdict(t) for t in tlist ]
答案 4 :(得分:0)
tolerance = 0.1
for i in tlist:
list2 = filter(lambda x:abs(sum(i)-sum(x))<tolerance,tdict
print [tdict[itm] for itm in list2]
我认为这样可行......但不是正面的......事实上它看起来并没有给你所需的输出