Обрезать значения массива с индексом min + max, заданным в целевой массив с требуемым индексом min + max - PullRequest
3 голосов
/ 26 ноября 2011

У меня какое-то время были проблемы с этим, поэтому я подумал, что могу спросить здесь.По сути, мне нужно «обрезать» значения массива с указанием минимального и максимального индексов в некотором целевом массиве с желаемым минимальным и максимальным индексом (минимальный и максимальный индексы вращаются вокруг 0), а размеры массивов учитывают различия между минимальным и максимальным,Конечно, фактический массив начинается с индекса 0, но смещение к реальным данным может быть другим.

Я попробовал (см. Ниже), но у меня возникли некоторые трудности.Моя математика действительно плохая.Код организован в виде теста JUnit для простоты запуска, а также для того, чтобы вы могли увидеть ожидаемые результаты.Я не думаю, что механизм в алгоритме дифференциации различий площадей является хорошим - должно быть более общее решение, где одна и та же линия может использоваться для всех случаев.Что-то в этом роде.

Это не домашняя работа или что-то в этом роде, она предназначена для обрезки сетки объектов, так что я могу динамически уменьшать и увеличивать сетку.Это всего лишь шаг 1.

Где я ошибся?

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

1 Ответ

1 голос
/ 26 ноября 2011

Следующие строки

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 вы можете исчерпать границы исходного / целевого массива).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...