将具有最小+最大索引的数组值裁剪到具有所需最小+最大索引的目标数组中
我已经被这个问题困扰了一段时间,所以我想我应该在这里问一下。基本上,我需要“裁剪”数组值,将最小和最大索引给定到某个目标数组中,并具有所需的最小和最大索引(最小和最大索引围绕 0 旋转),并且数组大小尊重最小和最大之间的差异。当然,实际数组从索引 0 开始,但实际数据的偏移量可能不同。
我已经尝试过(见下文),但遇到了一些困难。我的数学实在是太差了。该代码被安排为 JUnit 测试,以便于运行,同时您也可以看到预期的结果。我认为区分区域差异的算法中的机制不是一个好的机制——必须有一个更通用的解决方案,其中同一条线可以用于所有情况。类似的事情。
这不是家庭作业或类似的东西,它是用于裁剪对象网格,以便我可以动态缩小和放大网格。这只是第一步。
我哪里出错了?
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
public class Hmm {
@Test
public void shrinkTest1() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -1, 2);
int[] exp = new int[] { 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest1() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 4);
int[] exp = new int[] { 0, 3, 4, 5, 6, 7, 8, 0 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest2() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 6);
int[] exp = new int[] { 0, 3, 4, 5, 6, 7, 8, 0, 0, 0 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest1() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 2);
int[] exp = new int[] { 0, 3, 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
public int[] arrMod(int[] data, int min, int max, int newmin, int newmax) {
int minDiff = newmin - min;
int maxDiff = newmax - max;
System.out.println("minDiff: " + minDiff + ", maxDiff: " + maxDiff);
int[] newdata = new int[newmax - newmin + 1];
if ((newmax - newmin) > (max - min)) {
System.arraycopy(data, 0, newdata, maxDiff, max - min + 1);
} else if ((newmax - newmin) < (max - min)) {
System.arraycopy(data, minDiff, newdata, 0, newmax - newmin + 1);
} else {
// ...
}
return newdata;
}
编辑:我已经可以使用以下代码,但是子案例之间是否有任何合并改进可以使代码更小?我不喜欢他们的样子。另外,我正在使用 Object[],但如果它不能与 Integer[] 一起使用,请随意将其转回 int[] 进行测试。
public static final <T> T[] arrMod(T[] data, int min, int max, int newmin, int newmax) {
//System.out.println(
// "arrMod(data=" + Arrays.toString(data) + ",min=" + min + ",max=" + max +
// ",newmin=" + newmin + ",newmax=" + newmax + ")"
//);
int minDiff = newmin - min;
int maxDiff = newmax - max;
//System.out.println("minDiff: " + minDiff + ", maxDiff: " + maxDiff);
@SuppressWarnings("unchecked")
T[] newdata = (T[])Array.newInstance(data.getClass().getComponentType(), newmax - newmin + 1);
System.out.println("newdata: " + newdata);
if ((maxDiff - minDiff) > 0) {
// grow
//System.out.println("expand: (maxDiff - minDiff) > 0");
arraycopy(data, 0, newdata, -minDiff, max - min + 1);
} else if ((maxDiff - minDiff) < 0) {
// shrink
//System.out.println("shrink: (maxDiff - minDiff) < 0");
arraycopy(data, minDiff, newdata, 0, newmax - newmin + 1);
} else {
// move
//System.out.println("same: (maxDiff - minDiff) == 0");
if (min > newmin) {
arraycopy(data, 0, newdata, -minDiff, max - min + maxDiff + 1);
} else {
arraycopy(data, maxDiff, newdata, 0, max - min - maxDiff + 1);
}
}
return newdata;
}
编辑2:改进的测试用例:
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
public class Hmm {
@Test
public void shrinkTest1() {
System.out.println();
System.out.println("======= SHRINK TEST 1 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -1, 2);
Integer[] exp = new Integer[] { 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void shrinkTest2() {
System.out.println();
System.out.println("======= SHRINK TEST 2 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, -5, 4, -1, 2);
Integer[] exp = new Integer[] { 5, 6, 7, 8 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest1() {
System.out.println();
System.out.println("======= EXPAND TEST 1 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 4);
Integer[] exp = new Integer[] { null, 3, 4, 5, 6, 7, 8, null };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest2() {
System.out.println();
System.out.println("======= EXPAND TEST 2 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 6);
Integer[] exp = new Integer[] { null, 3, 4, 5, 6, 7, 8, null, null, null };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest1() {
System.out.println();
System.out.println("======= SAME TEST 1 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 2);
Integer[] exp = new Integer[] { null, 3, 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest2() {
System.out.println();
System.out.println("======= SAME TEST 2 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -1, 4);
Integer[] exp = new Integer[] { 4, 5, 6, 7, 8, null };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest3() {
System.out.println();
System.out.println("======= SAME TEST 3 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -4, 1);
Integer[] exp = new Integer[] { null, null, 3, 4, 5, 6 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
I've been having trouble with this for a while, so I thought I'd ask here. Basically, I need to 'crop' array values with a min and max index given into some target array, with a desired min and max index (the min and max index revolve around 0), and array sizes respect the differences between min and max. The actual array starts from index 0, of course, but the offset to real data might be different.
I've had a go at it (see below), but I'm having some difficulty. My math is really poor. The code is arranged as a JUnit test for easy running, and also so you can see what the expected results are. I don't think the mechanism in the algorithm of differentiating between area differences is a good one -- there must be a more general solution, where the same line can be used for all cases. Something like that.
This isn't homework or anything like that, it's for cropping of a grid of objects, so that I can shrink and enlarge the grid dynamically. This is just step 1.
Where have I gone wrong?
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
public class Hmm {
@Test
public void shrinkTest1() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -1, 2);
int[] exp = new int[] { 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest1() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 4);
int[] exp = new int[] { 0, 3, 4, 5, 6, 7, 8, 0 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest2() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 6);
int[] exp = new int[] { 0, 3, 4, 5, 6, 7, 8, 0, 0, 0 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest1() {
int[] res = arrMod(new int[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 2);
int[] exp = new int[] { 0, 3, 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
public int[] arrMod(int[] data, int min, int max, int newmin, int newmax) {
int minDiff = newmin - min;
int maxDiff = newmax - max;
System.out.println("minDiff: " + minDiff + ", maxDiff: " + maxDiff);
int[] newdata = new int[newmax - newmin + 1];
if ((newmax - newmin) > (max - min)) {
System.arraycopy(data, 0, newdata, maxDiff, max - min + 1);
} else if ((newmax - newmin) < (max - min)) {
System.arraycopy(data, minDiff, newdata, 0, newmax - newmin + 1);
} else {
// ...
}
return newdata;
}
Edit: I've got it working with the following code, but are there any merging improvements between the sub-cases which can be made to make the code smaller? I don't like the look of them. Also, I'm using Object[], but feel free to turn it back to int[] for testing if it doesn't work with Integer[].
public static final <T> T[] arrMod(T[] data, int min, int max, int newmin, int newmax) {
//System.out.println(
// "arrMod(data=" + Arrays.toString(data) + ",min=" + min + ",max=" + max +
// ",newmin=" + newmin + ",newmax=" + newmax + ")"
//);
int minDiff = newmin - min;
int maxDiff = newmax - max;
//System.out.println("minDiff: " + minDiff + ", maxDiff: " + maxDiff);
@SuppressWarnings("unchecked")
T[] newdata = (T[])Array.newInstance(data.getClass().getComponentType(), newmax - newmin + 1);
System.out.println("newdata: " + newdata);
if ((maxDiff - minDiff) > 0) {
// grow
//System.out.println("expand: (maxDiff - minDiff) > 0");
arraycopy(data, 0, newdata, -minDiff, max - min + 1);
} else if ((maxDiff - minDiff) < 0) {
// shrink
//System.out.println("shrink: (maxDiff - minDiff) < 0");
arraycopy(data, minDiff, newdata, 0, newmax - newmin + 1);
} else {
// move
//System.out.println("same: (maxDiff - minDiff) == 0");
if (min > newmin) {
arraycopy(data, 0, newdata, -minDiff, max - min + maxDiff + 1);
} else {
arraycopy(data, maxDiff, newdata, 0, max - min - maxDiff + 1);
}
}
return newdata;
}
Edit 2: Improved testcases:
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
public class Hmm {
@Test
public void shrinkTest1() {
System.out.println();
System.out.println("======= SHRINK TEST 1 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -1, 2);
Integer[] exp = new Integer[] { 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void shrinkTest2() {
System.out.println();
System.out.println("======= SHRINK TEST 2 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, -5, 4, -1, 2);
Integer[] exp = new Integer[] { 5, 6, 7, 8 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest1() {
System.out.println();
System.out.println("======= EXPAND TEST 1 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 4);
Integer[] exp = new Integer[] { null, 3, 4, 5, 6, 7, 8, null };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void expandTest2() {
System.out.println();
System.out.println("======= EXPAND TEST 2 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 6);
Integer[] exp = new Integer[] { null, 3, 4, 5, 6, 7, 8, null, null, null };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest1() {
System.out.println();
System.out.println("======= SAME TEST 1 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -3, 2);
Integer[] exp = new Integer[] { null, 3, 4, 5, 6, 7 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest2() {
System.out.println();
System.out.println("======= SAME TEST 2 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -1, 4);
Integer[] exp = new Integer[] { 4, 5, 6, 7, 8, null };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
@Test
public void sameTest3() {
System.out.println();
System.out.println("======= SAME TEST 3 ========");
Integer[] res = WFMap.arrMod(new Integer[] { 3, 4, 5, 6, 7, 8 }, -2, 3, -4, 1);
Integer[] exp = new Integer[] { null, null, 3, 4, 5, 6 };
assertArrayEquals("Array " + Arrays.toString(res) + " not equal to expected " + Arrays.toString(exp), exp, res);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
以下几行
表示目标目的地是使用
max
值确定的,而应由min
值确定(起始索引始终为min
)。你必须考虑两种情况。如果新的最小值小于旧的最小值,您可以从头开始复制数据并将其稍微向右移动。否则,您必须从一开始就删除一些值,即从大于零的索引进行复制。
请注意,根据您的用例,此代码可能需要对溢出进行更多检查(例如,对于较大的
minDiff
值,您可能会超出源/目标数组范围)。The following lines
indicate that the target destination is determined using the
max
values while it should be done by themin
values (starting index is alwaysmin
).You have to consider two cases. If the new min is smaller than the old one you can copy the data from start and shift it somewhat to the right. Otherwise you have to remove some values from the start, i.e. copy from an index larger than zero.
Please note that this code might need some more checks on overflow depending on your use cases (e.g. for large values of
minDiff
you might run out of the source/target array bounds).