【发布时间】:2017-03-11 00:27:32
【问题描述】:
我有一个数字列表,我需要对它进行分组。 itertools.grouby 非常适用于相同数字的序列,但对于具有阈值 (2-3%) 的数字,我需要相同的行为
E.X:lst = [1, 500, 19885, 19886, 19895, 90000000]
我期待[[1], [500], [19885, 19886, 19895], [90000000]]
你能给我一些建议吗?
【问题讨论】:
我有一个数字列表,我需要对它进行分组。 itertools.grouby 非常适用于相同数字的序列,但对于具有阈值 (2-3%) 的数字,我需要相同的行为
E.X:lst = [1, 500, 19885, 19886, 19895, 90000000]
我期待[[1], [500], [19885, 19886, 19895], [90000000]]
你能给我一些建议吗?
【问题讨论】:
您仍然可以使用groupby,但使用自定义比较器:
class MyValue:
def __init__(self, val):
self.val = val
def __eq__(self, other):
# 2% leeway
return self.val*0.98 <= other.val <= self.val*1.02
然后:
for key, group in groupby(map(MyValue, values)):
group_values = [el.val for el in group]
请注意,这会将第一个值保留为“参考”,因此在一个组中,元素与键/第一个值的距离最多为 2%,但在组内,偏差可能高达 4 %。
对于您显示的数据,这应该没问题,如果不同的组之间存在显着差异,但对于靠近的组来说就不可靠了。
【讨论】:
res = [[el.val for el in g] for key, g in groupby(map(MyValue, values))] 而不是第二个代码块。
将它们存储起来。您需要提前手动计算休息时间。那你能提前排序吗?这样会更容易。
实际上,如果您使用对数,则乘法阈值会变成常数阈值,例如0.98..1.02 in log-land ~= (-0.02, +0.02)。 因此,请使用所有号码的日志。 在进行 groupby 之前,您仍然需要存储它们。
如果您需要代码,请给我们一个更好的(随机种子)可重现示例,其中包含更多测试极端情况的数字。
【讨论】: