简单地铺地板和拼接怎么样?
data = [ {'a': 0.197, 'b': 0.201, 'c': 0.199, 'd': 0.202, 'e': 0.201}, {'a': 0.624, 'b': 0.628, 'c': 0.623, 'd': 0.625, 'e': 0.750}, {'a': 0.192, 'b': 0.203, 'c': 0.200, 'd': 0.202, 'e': 0.203}, {'a': 0.630, 'b': 0.620, 'c': 0.625, 'd': 0.623, 'e': 0.752}, ]
def hashwithtol(datum, abstol=0.1):
return ','.join(
str(int(datum[k] // abstol))
for k in 'abcde'
)
def groupby_hashwithtol(data, abstol=0.1):
groups = {}
for datum in data:
groups.setdefault(hashwithtol(datum, abstol), []).append(datum)
return groups
for abstol in (1, 0.1, 0.01):
print(f'Abs tol = {abstol}')
groups = groupby_hashwithtol(data, abstol)
print(*(f'{k}: {g}' for k,g in groups.items()), sep='\n')
print()
Abs tol = 1
0,0,0,0,0: [{'a': 0.197, 'b': 0.201, 'c': 0.199, 'd': 0.202, 'e': 0.201}, {'a': 0.624, 'b': 0.628, 'c': 0.623, 'd': 0.625, 'e': 0.75}, {'a': 0.192, 'b': 0.203, 'c': 0.2, 'd': 0.202, 'e': 0.203}, {'a': 0.63, 'b': 0.62, 'c': 0.625, 'd': 0.623, 'e': 0.752}]
Abs tol = 0.1
1,2,1,2,2: [{'a': 0.197, 'b': 0.201, 'c': 0.199, 'd': 0.202, 'e': 0.201}]
6,6,6,6,7: [{'a': 0.624, 'b': 0.628, 'c': 0.623, 'd': 0.625, 'e': 0.75}, {'a': 0.63, 'b': 0.62, 'c': 0.625, 'd': 0.623, 'e': 0.752}]
1,2,2,2,2: [{'a': 0.192, 'b': 0.203, 'c': 0.2, 'd': 0.202, 'e': 0.203}]
Abs tol = 0.01
19,20,19,20,20: [{'a': 0.197, 'b': 0.201, 'c': 0.199, 'd': 0.202, 'e': 0.201}]
62,62,62,62,74: [{'a': 0.624, 'b': 0.628, 'c': 0.623, 'd': 0.625, 'e': 0.75}]
19,20,20,20,20: [{'a': 0.192, 'b': 0.203, 'c': 0.2, 'd': 0.202, 'e': 0.203}]
62,61,62,62,75: [{'a': 0.63, 'b': 0.62, 'c': 0.625, 'd': 0.623, 'e': 0.752}]
- 如果你更喜欢四舍五入而不是地板,那么你可以用
int(round(datum[k] / abstol))
代替int(datum[k] // abstol)
.
- 在上面的示例中,您可以注意到0.199和0.2不会被放在同一个垃圾桶中,因为0.199被压到了0.1.使用四舍五入而不是地板不能解决这个问题,只需将问题移到不同的数字;例如,0.149将向下舍入为0.1,而0.150将向上舍入为0.2.
- 如果每个DICT有5个以上的值,并且键开始变得太长,则可以将其包装在对Python的内置
hash
:def hashwithtol(datum, abstol=0.1): return hash(','.join(str(int(datum[k] // abstol)) for k in 'abcde'))
的调用中