Удалить элемент из списка при выполнении итераций на основе отношений с предыдущими и последующими элементами - PullRequest
0 голосов
/ 20 сентября 2019

Существует много вопросов о переполнении стека о том, как удалять элементы из коллекции при ее повторении (особенно в Java). Этот вопрос имеет приличный набор вариантов, как это сделать.Однако ни одно из условий удаления, описанных в этих ответах, не является функцией отношения записи к соседним записям .В качестве примера ...

Представьте, что у меня есть список точек x, y, и я хочу сократить список так, чтобы ни одна серия из 3 или более точек не была коллинеарной.Другими словами, я хочу иметь возможность сократить список точек так, чтобы они описывали начальную / конечную точки серии отрезков, так что никакие два отрезка не являются подразделами одного большего сегмента.Например, данный набор может выглядеть как [{0,0}, {3,0}, {5,2}, {7,4}, {10,4}] , и я быхотите уменьшить его до набора [{0,0}, {3,0}, {7,4}, {10,4}] , поскольку точка {5,2} является коллинеарнойс {3,0} и {7,4}.Тест коллинеарности зависит от предыдущей и последующей точек в наборе, поэтому невозможно узнать, нужно ли удалять данную точку на основе одной этой точки, что является требованием для большинства вариантов ответа, связанного выше,как метод removeIf().

Мой вопрос прост: существует ли в Java способ сокращения списка таким образом за один проход набора данных?Очевидно, что я мог бы выполнить итерацию по ней один раз, проверить каждую точку на коллинеарность с соседями и сохранить индексы точек для удаления, а затем за второй проход взять только нужные точки и создать новый набор.

1 Ответ

1 голос
/ 24 сентября 2019

Как упоминалось в комментариях, вы можете использовать removeIf / streams.

foreach / итератор выдаст ConcurrentModificationException, если вы попытаетесь удалить элемент во время итерации, но должен работать стандарт для цикла.Ведение отдельного счетчика для количества пройденных вами предметов (отдельно от индекса).Вот пример, который должен работать для начальной проблемы, которую вы обрисовали в общих чертах:

        ArrayList<R4NPoint> arrList = new ArrayList<R4NPoint>() {{
            add(new R4NPoint(0, 0));
            add(new R4NPoint(3, 0));
            add(new R4NPoint(5, 2));
            add(new R4NPoint(7, 4));
            add(new R4NPoint(9, 6));
            add(new R4NPoint(5, 0));
            add(new R4NPoint(10, 4));
            add(new R4NPoint(15, 8));
        }};

        // start at the second item as our check is always dependent on our previous and next neighbors
        int index = 1;
        int totalSize = arrList.size();
        for (int numberOfItemsChecked = 1; numberOfItemsChecked < totalSize - 1; numberOfItemsChecked++) {
            int prevIndex = index - 1;
            int nextIndex = index + 1;
            // check previous and next for removal condition
            if (arrList.get(index).arePointsColinear(arrList.get(prevIndex), arrList.get(nextIndex))) {
                // if they are co-linear remove the item at our current index, and don't increment the index
                // the next item will now be at the current index
                arrList.remove(index);
            } else {
                index++;
            }
        }
        System.out.println("finalArrayAfterRemoval = " + arrList.toString());

, что приведет к выводу:

finalArrayAfterRemoval = [{0, 0}, {3, 0}, {9, 6}, {5, 0}, {15, 8}]

Я остановил реализацию R4NPoint какЯ предполагаю, что у вас уже есть что-то, что может повлиять на вас.

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