Bagaimana untuk mengalih keluar elemen dengan cekap daripada kepingan dalam Go?

PHPz
Lepaskan: 2024-02-08 22:03:22
ke hadapan
705 orang telah melayarinya

如何在 Go 中高效地从切片中删除元素?

editor php Apple memperkenalkan anda cara memadamkan elemen dengan cekap daripada kepingan dalam Go. Dalam bahasa Go, pemadaman elemen dalam hirisan adalah operasi biasa Walau bagaimanapun, disebabkan oleh ciri hirisan, pemadaman terus elemen boleh menyebabkan panjang hirisan berubah, sekali gus menjejaskan operasi seterusnya. Untuk memadamkan elemen dalam kepingan dengan cekap, kita boleh menggunakan ciri kepingan dan beberapa fungsi terbina dalam untuk mencapai ini. Beberapa kaedah yang biasa digunakan akan diperkenalkan secara terperinci di bawah.

Kandungan soalan

Terdapat pelbagai cara untuk mengalih keluar elemen hirisan. Tetapi bagaimana jika saya mempunyai aplikasi yang melakukan banyak pemprosesan kepingan? Potongan Go dioptimumkan dengan baik untuk menambah elemen baharu, tetapi adakah terdapat cara yang cekap untuk mengalih keluar elemen daripada kepingan (bukan sahaja untuk kelajuan, tetapi juga dioptimumkan memori).

Saya sedar tentang kepingan. Padam fungsi yang diperkenalkan dalam Go 1.21, tetapi di sebalik tabir ia menggunakan teknik terkenal berikut:

return append(s[:i], s[j:]...)
Salin selepas log masuk

Nampaknya tatasusunan asas tidak dikurangkan dalam kes ini. Ini bagus untuk kelajuan, tetapi bagaimana jika kita mempunyai banyak elemen (seperti 100k atau 1M) dan kemudian mengurangkannya kepada sangat sedikit (seperti hanya 10)? Nampaknya tiada pengoptimuman memori seperti yang digunakan untuk meningkatkan kapasiti kepingan.

Apabila kita tidak perlu mengekalkan susunan elemen dalam kepingan, kita boleh menggunakan kaedah berikut (pergi ke pautan taman permainan):

func sliceDel[S ~[]E, E any](s S, i, j int) S {
    lastIdx := len(s) - (j - i)
    copy(s[i:], s[lastIdx:])
    return s[:lastIdx]
}
Salin selepas log masuk

Ini berguna apabila kita mempunyai kepingan besar dan sebilangan kecil elemen untuk dialih keluar (idea di sebaliknya adalah untuk menyalin sebilangan kecil elemen kepingan).

Mengenai memori, kapasiti adalah sama dalam kedua-dua kes dan tidak akan berkurangan. Contohnya:

// Reduce slice almost to zero
    for i := 0; i < sliceSize/2-1; i++ {
        sl = sliceDel(sl, 0, 2)
    }
    fmt.Printf("len = %d, cap = %d", len(sl), cap(sl))
        // Output: len = 2, cap = 100000

    // Reduce slice almost to zero
    for i := 0; i < sliceSize/2-1; i++ {
        sl = slices.Delete(sl, 0, 2)
    }
    fmt.Printf("len = %d, cap = %d", len(sl), cap(sl))
        // Output: len = 2, cap = 100000
Salin selepas log masuk

Jadi, adakah cara untuk mengoptimumkan penggunaan memori? Sebagai contoh, jika panjang kepingan kurang daripada separuh kapasitinya, kurangkan kapasiti sebanyak separuh.

Saya juga ingin tahu cara melakukan ini dengan cekap, seperti teknik seperti ini s[:len(s):len(s)] (ungkapan kepingan penuh yang digunakan oleh kepingan.Klip) tidak mengurangkan tatasusunan asas - ia hanya menjimatkan kapasiti baharu dalam struktur kepingan untuk mengelakkan penambahan new Mengatasi elemen kepingan induk apabila elemen itu dilampirkan pada kepingan anak (seperti yang dinyatakan dalam cadangan ini).

Penyelesaian

Tiada penyelesaian "biasanya terbaik". Anda telah menunjukkan berbilang pendekatan dalam soalan anda, setiap satunya mungkin lebih baik daripada yang lain untuk senario tertentu.

Jika anda berada dalam situasi seperti ini, apabila anda ingin menyimpan beberapa elemen daripada banyak, jangan mula padam elemen tersebut. Bina kepingan baharu dengan unsur-unsur ini. Selain lebih pantas, ini pasti menyelesaikan masalah ingatan juga.

Anda tidak boleh mengurangkan penggunaan memori dengan menggunakan ungkapan kepingan penuh selain daripada memperuntukkan dan menggunakan kepingan baharu. Selagi terdapat rujukan kepada tatasusunan sokongan, ia tidak akan mengecut (sekurang-kurangnya tidak dalam versi semasa Go). Jika anda menghadapi situasi di mana tatasusunan sandaran yang besar diperuntukkan tetapi hanya sebahagian kecil daripadanya digunakan, anda boleh memperuntukkan sekeping baharu dan menyalin elemen secara manual untuk membolehkan tatasusunan besar dikumpul sampah.

Pertimbangkan juga bahawa jika anda mempunyai kepingan yang sangat besar yang mungkin anda perlukan untuk mengalih keluar banyak elemen, satu kepingan mungkin bukan struktur data terbaik untuk digunakan. Sebagai contoh, anda boleh cuba menggunakan senarai terpaut, atau anda juga boleh mencuba peta: memadamkan elemen daripada senarai terpaut atau peta akan menjadi lebih pantas dan pemetaan juga akan memberikan masa carian yang pantas (O(n)), seperti yang ditunjukkan di bawah.

Atas ialah kandungan terperinci Bagaimana untuk mengalih keluar elemen dengan cekap daripada kepingan dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!