我有一个数组中的值列表(从低到高排序),我打算显示这些值分布在一行上,但由于某些值接近,这些点最终会重叠。由于确切的值并不重要,小的调整无关紧要,我正在尝试制作一些代码,这些代码可以传播任何值的集群,使得它们比其他任何值都更接近.5。
例如,假设我们有这个数组:
my_values = { 0.2, 1.3, 2.0, 2.1, 2.5, 3.6, 5.2 }
2.0,2.1和2.5太靠近了,所以我需要移动它们,因此它们不会比.5更接近但是尽可能接近实际值。因此,最佳解决方案将是:
my_values = { 0.2, 1.1, 1.6, 2.1, 2.6, 3.6, 5.2 }
到目前为止,这是我的代码,它只是对解决方案的蹩脚尝试(我的代码中列表中的实际项目是具有get / set函数的对象,但原理是相同的):
...
last_dot = -999 'Low enough
For Each dot In my_values
If dot.getPos <= last_dot + 0.5 Then
dot.setPos last_dot + 0.5
End If
last_dot = dot.getPos
Next dot
有些事情我不确定如何解决: 我喜欢将它们上下传播,所以任何一个cluser的中心都不会被移动。到目前为止,我所做的每一个动作都只是提高了值,并且群集的最后一个值比其他值更加偏移,最好是向上移动的任何值都应该向下移动另一个值。保持任何值的最大调整尽可能低。所以在上面的列表中,当2.0向下移动到1.6时,它太接近1.3,所以必须移动到1.1,但在我的代码中我不知道在检查1.3项时。 (不确定我是否解释过,所以任何人都可以理解= /)
任何有用的帮助!
答案 0 :(得分:2)
整个阵列的迭代放松:
输入:
{ 0.2, 1.3, 2.0, 2.1, 2.5, 3.6, 5.2 }
功能:
for (int j = 0; j < 100; j++)// 100 is extreme, maybe 20 is enough for short anomalies
{
for (int i = 0; i < t.Length - 1; i++)
{
if (t[i] > t[i + 1] - 0.5)
{
t[i] -= (t[i] - (t[i + 1] - 0.5)) * 0.1;
}
}
for (int i = t.Length - 1; i >= 1; i--)
{
if (t[i] < t[i - 1] + 0.5)
{
t[i] -= (t[i] - (t[i - 1] + 0.5)) * 0.1;
}
}
}
结果:
0,2
1,00031552491128
1,61163875308098
2,1160023905259
2,66
3,6
5,2
警告:当只需要改变一些元素时,O(n)效率不高。
编辑:将代码更正为A.S.H.评论
新输出:
0,2
1,21857842635286
1,71823144559425
2,21771136663457
2,71733660405361
3,6
5,2
因此它看起来更加对称,现在更接近点2.05,这是点太近的点的中点。