将数组均匀截断到 Java 中的给定长度限制

Evenly truncate an array to a given length limit in Java

我得到了一个比常数整数 limit 更长的数组。我需要将数组截断到长度 limit。但稍后,该数组将包含折线图的点。如果我得到很多点,甚至无法在浏览器中显示,我想“缩小”该数据。因此,我只想删除均匀分布序列中的数据条目。

我试过这个:

final Object[] array = /* some array */;
final List<Object> result = * some list */;
final int limit = /* some limit; but suppose that array.length > limit */
final double r = (array.length - limit) / (double) array.length;
double m = 0;
for (int i = 0; i < array.length; i++) {
    while (m >= 1) {
        m -= 1;
    }
    m += r;
    if (m < 1) {
        result.add(array[i]);
    }
}

问题是:结果的长度是否总是恰好 limit 而 why/why 不是?

这可能会完成工作:

public static <T> List<T> limitArray(T[] array, int limit) {
    if (limit > array.length) {
        return Arrays.asList(array);
    }
    List<T> list = new ArrayList<T>();
    double stepSize = ((double) array.length - 1) / ((double) limit - 1);
    double i = 0;
    while (i < array.length) {
        list.add(array[(int) i]);
        i += stepSize;
    }
    return list;
}

为什么 array.length - 1limit - 1
因为第一个和最后一个元素总是相加的,剩下的会平分。
既然你说"the array will contain the points of a line diagram",我觉得最好保留第一个和最后一个元素,以保持图的全宽。

由于除法结果的有限精度 doubles,数组中的一个元素可能太少了。在那种情况下,这是一个可能的解决方案:

  • list.add(array[(int) i]) 替换为 list.add(array[(int) Math.round(i)])。请注意,这样做还会影响添加到列表中的数组的其他索引。

旧答案:
你为什么不这样做呢?:

public <T> List<T> limitArray(T[] array, int limit) {
    List<T> list = new ArrayList<T>();
    int i = 0;
    while (i < arrary.length && i < limit) {
        list.add(array[i]);
        i++;
    }
    return list;
}

继续对双精度求和是个坏主意,因为您可能会因舍入误差而出现故障。基于 MC Emperor 的回答:

public <T> List<T> limitArray(T[] array, int limit) {
    List<T> list = new ArrayList<T>();
    int i = 0;
    double scale = array.length * 1.0/limit;
    while (i < limit) {
        list.add(array[(int)(i * scale)]);
        i++;
    }
    return list;
}

这可以保证您的物品分布均匀,并且您有 limit 件物品。 *1.0是强制加倍。