【问题标题】:Crop array values with min+max index given into a target array with a desired min+max index将具有 min+max 索引的数组值裁剪到具有所需 min+max 索引的目标数组中
【发布时间】:2012-01-06 18:25:59
【问题描述】:

这个问题我已经有一段时间了,所以我想我会在这里问。基本上,我需要将具有最小和最大索引的数组值“裁剪”到某个目标数组中,并具有所需的最小和最大索引(最小和最大索引围绕 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[],但可以随意将其转回 int[] 以测试它是否不适用于 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;
}

编辑 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);
    }

【问题讨论】:

    标签: java arrays algorithm math


    【解决方案1】:

    以下几行

    if ((newmax - newmin) > (max - min)) {
        System.arraycopy(data, 0, newdata, maxDiff, max - min + 1);
    } 
    

    表示目标目的地是使用max 值确定的,而它应该由min 值完成(起始索引始终为min)。

    您必须考虑两种情况。如果新的最小值小于旧的最小值,您可以从头开始复制数据并将其稍微向右移动。否则,您必须从一开始就删除一些值,即从大于零的索引中复制。

    if (minDiff < 0) {
        System.arraycopy(data, 0, newdata, -minDiff, max - min + 1);
    } else {
        System.arraycopy(data, minDiff, newdata, 0, max - min + 1);
    }
    

    请注意,根据您的用例,此代码可能需要对溢出进行更多检查(例如,对于较大的 minDiff 值,您可能会超出源/目标数组边界)。

    【讨论】:

    • 嘿,感谢您的帮助 :) 您的放大代码在所有情况下都有效,但不能缩小代码,并且猜测没有大小变化的运动代码有点棘手(尽管您认为那会是最容易处理的情况..奇怪)。但是,您有什么优化的想法吗?
    猜你喜欢
    • 2016-08-27
    • 2013-06-22
    • 2022-12-16
    • 2020-08-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    • 2018-04-18
    • 2012-10-28
    相关资源
    最近更新 更多