Ada banyak pertanyaan di Stack Overflow tentang cara menghapus item dari koleksi saat mengulanginya (khususnya di Java). Pertanyaan ini memiliki serangkaian opsi yang layak tentang cara melakukannya. Namun, tidak satu pun dari kondisi penghapusan yang dijelaskan dalam jawaban tersebut adalah fungsi dari hubungan entri dengan entri tetangganya. Sebagai contoh...

Bayangkan saya memiliki daftar titik x,y, dan saya ingin mengurangi daftar tersebut sehingga tidak ada rangkaian 3 titik atau lebih yang kolinear. Dengan kata lain, saya ingin dapat mengurangi daftar titik sedemikian rupa sehingga mereka menggambarkan titik awal/akhir dari serangkaian segmen garis sehingga tidak ada dua segmen yang merupakan subbagian dari satu segmen yang lebih besar. Misalnya, satu set yang diberikan mungkin terlihat seperti [ {0,0}, {3,0}, {5,2}, {7,4}, {10,4} ], dan saya ingin menguranginya ke set [ {0,0}, {3,0}, {7,4}, {10,4} ], karena titik {5,2} kolinear dengan {3,0 } dan {7,4}. Uji kolinearitas tergantung pada titik sebelumnya dan selanjutnya dalam himpunan, jadi tidak mungkin untuk mengetahui apakah titik tertentu perlu dihapus berdasarkan titik itu saja, yang merupakan persyaratan untuk sebagian besar opsi dalam jawaban yang ditautkan di atas, seperti metode removeIf().

Pertanyaan saya sederhana: apakah ada cara di Jawa untuk mengurangi daftar dengan cara ini dalam satu lintasan dari kumpulan data? Jelas saya dapat mengulanginya sekali, menguji setiap titik untuk kolinearitas dengan tetangganya, dan menyimpan indeks poin untuk dihapus, dan kemudian dalam lintasan kedua hanya mengambil poin yang diinginkan dan membangun set baru.

0
MattS 20 September 2019, 23:45

1 menjawab

Jawaban Terbaik

Seperti yang disebutkan dalam komentar, Anda dapat menggunakan removeIf/streams.

Foreach/iterator akan memberikan ConcurrentModificationException jika Anda mencoba menghapus item saat iterasi, tetapi standar for loop akan berfungsi. Mempertahankan penghitung terpisah untuk jumlah item yang telah Anda lalui (terpisah dari indeks). Berikut adalah contoh yang akan berfungsi untuk contoh masalah awal yang Anda uraikan:

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

Yang akan menghasilkan output:

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

Saya telah meninggalkan implementasi R4NPoint karena saya berasumsi Anda sudah memiliki sesuatu yang mempengaruhi Anda.

1
R4N 24 September 2019, 17:08