将数组均匀截断到 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 - 1
和 limit - 1
?
因为第一个和最后一个元素总是相加的,剩下的会平分。
既然你说"the array will contain the points of a line diagram",我觉得最好保留第一个和最后一个元素,以保持图的全宽。
由于除法结果的有限精度 double
s,数组中的一个元素可能太少了。在那种情况下,这是一个可能的解决方案:
- 将
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
是强制加倍。
我得到了一个比常数整数 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 - 1
和 limit - 1
?
因为第一个和最后一个元素总是相加的,剩下的会平分。
既然你说"the array will contain the points of a line diagram",我觉得最好保留第一个和最后一个元素,以保持图的全宽。
由于除法结果的有限精度 double
s,数组中的一个元素可能太少了。在那种情况下,这是一个可能的解决方案:
- 将
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
是强制加倍。