Saya baru saja menulis fungsi string reverse di C # 2.0 (yaitu LINQ tidak tersedia) dan muncul dengan ini:
public string Reverse(string text)
{
char[] cArray = text.ToCharArray();
string reverse = String.Empty;
for (int i = cArray.Length - 1; i > -1; i--)
{
reverse += cArray[i];
}
return reverse;
}
Secara pribadi saya tidak tergila-gila dengan fungsi dan yakin bahwa ada cara yang lebih baik untuk melakukannya. Disana?
Jawaban:
sumber
Di sini solusi yang membalikkan string
"Les Mise\u0301rables"
dengan benar"selbare\u0301siM seL"
. Ini harus memberikan sepertiselbarésiM seL
, bukanselbaŕesiM seL
(perhatikan posisi aksen), seperti hasil sebagian besar implementasi berdasarkan unit kode (Array.Reverse
, dll) atau bahkan titik kode (membalikkan dengan perhatian khusus untuk pasangan pengganti).(Dan contoh menjalankan langsung di sini: https://ideone.com/DqAeMJ )
Itu hanya menggunakan. NET API untuk iterasi cluster grapheme , yang telah ada sejak itu, tetapi sedikit "tersembunyi" dari pandangan, tampaknya.
sumber
Ini ternyata menjadi pertanyaan yang sangat rumit.
Saya akan merekomendasikan menggunakan Array. Membalik sebagian besar kasus karena dikodekan secara asli dan sangat mudah untuk mempertahankan dan memahami.
Tampaknya mengungguli StringBuilder dalam semua kasus yang saya uji.
Ada pendekatan kedua yang bisa lebih cepat untuk panjang string tertentu yang menggunakan Xor .
Catatan Jika Anda ingin mendukung rangkaian karakter Unicode UTF16 baca ini . Dan gunakan implementasi di sana sebagai gantinya. Ini dapat dioptimalkan lebih lanjut dengan menggunakan salah satu dari algoritma di atas dan berjalan melalui string untuk membersihkannya setelah karakter dibalik.
Berikut ini adalah perbandingan kinerja antara metode StringBuilder, Array.Reverse dan Xor.
Inilah hasilnya:
Tampaknya Xor bisa lebih cepat untuk string pendek.
sumber
Jika Anda dapat menggunakan LINQ (.NET Framework 3.5+) daripada mengikuti satu liner akan memberi Anda kode pendek. Jangan lupa menambahkan
using System.Linq;
untuk memiliki akses keEnumerable.Reverse
:Catatan:
sumber
Jika string berisi data Unicode (karakter non-BMP), metode lain yang telah diposting akan merusaknya, karena Anda tidak dapat menukar urutan unit kode pengganti tinggi dan rendah saat membalikkan string. (Informasi lebih lanjut tentang ini dapat ditemukan di blog saya .)
Contoh kode berikut akan membalikkan string yang berisi karakter non-BMP dengan benar, mis., "\ U00010380 \ U00010381" (Huruf Ugaritik Alpa, Huruf Ugaritik Beta).
sumber
Oke, demi "jangan ulangi diri Anda," saya menawarkan solusi berikut:
Pemahaman saya adalah bahwa implementasi ini, tersedia secara default di VB.NET, dengan benar menangani karakter Unicode.
sumber
Greg Beech memposting
unsafe
opsi yang memang secepat mungkin (ini merupakan pembalikan di tempat); tetapi, seperti yang ditunjukkannya dalam jawabannya, itu adalah gagasan yang benar-benar membawa malapetaka .Yang mengatakan, saya terkejut ada begitu banyak konsensus yang
Array.Reverse
merupakan metode tercepat. Masih adaunsafe
pendekatan yang mengembalikan salinan string yang terbalik (tidak ada shenanigans pembalikan di tempat) secara signifikan lebih cepat daripadaArray.Reverse
metode untuk string kecil:Berikut ini beberapa hasil benchmark .
Anda dapat melihat bahwa peningkatan kinerja menyusut dan kemudian menghilang terhadap
Array.Reverse
metode saat string semakin besar. Untuk string berukuran kecil hingga sedang, sulit untuk mengalahkan metode ini.sumber
Jawaban yang mudah dan menyenangkan menggunakan Metode Ekstensi:
dan inilah hasilnya:
sumber
Reverse()
danToArray()
berada dalam urutan yang salah dalam sampel kode Anda.Jika Anda ingin memainkan permainan yang benar-benar berbahaya, maka ini adalah cara tercepat yang ada (sekitar empat kali lebih cepat daripada
Array.Reverse
metode ini). Ini adalah terbalik menggunakan pointer.Perhatikan bahwa saya benar-benar tidak merekomendasikan ini untuk penggunaan apa pun, pernah ( lihat di sini untuk beberapa alasan mengapa Anda tidak harus menggunakan metode ini ), tetapi hanya menarik untuk melihat bahwa itu dapat dilakukan, dan string tidak benar-benar berubah. setelah Anda mengaktifkan kode yang tidak aman.
sumber
unsafe
kode yang tidak jahat dan masih berdetakArray.Reverse
dalam banyak kasus. Lihatlah jawaban saya.Lihatlah entri wikipedia di sini . Mereka menerapkan metode ekstensi String.Reverse. Ini memungkinkan Anda untuk menulis kode seperti ini:
Mereka juga menggunakan kombinasi ToCharArray / Reverse yang disarankan oleh jawaban lain untuk pertanyaan ini. Kode sumber terlihat seperti ini:
sumber
Pertama, Anda tidak perlu memanggil
ToCharArray
string yang sudah dapat diindeks sebagai array char, jadi ini akan menghemat alokasi.Optimalisasi selanjutnya adalah menggunakan a
StringBuilder
untuk mencegah alokasi yang tidak perlu (karena string tidak dapat diubah, menyatukannya membuat salinan string setiap kali). Untuk lebih mengoptimalkan ini, kami telah mengatur sebelumnya panjangStringBuilder
sehingga tidak perlu memperluas buffer-nya.Edit: Data Kinerja
Saya menguji fungsi ini dan menggunakan fungsi
Array.Reverse
dengan program sederhana berikut, di manaReverse1
satu fungsi danReverse2
yang lainnya:Ternyata untuk string pendek
Array.Reverse
metode ini sekitar dua kali lebih cepat dari yang di atas, dan untuk string yang lebih panjang perbedaannya bahkan lebih jelas. Jadi mengingat bahwaArray.Reverse
metode ini lebih sederhana dan lebih cepat, saya sarankan Anda menggunakannya daripada yang ini. Saya meninggalkan yang ini di sini hanya untuk menunjukkan bahwa itu bukan cara yang harus Anda lakukan (sangat mengejutkan saya!)sumber
Coba gunakan Array. Balikkan
sumber
Tentu saja Anda dapat memperluas kelas string dengan metode Reverse
sumber
Enumerable.Reverse(input)
sama denganinput.Reverse()
"Terbaik" dapat bergantung pada banyak hal, tetapi berikut beberapa alternatif pendek yang dipesan dari cepat ke lambat:
sumber
Dimulai dengan .NET Core 2.1 ada cara baru untuk membalikkan string menggunakan
string.Create
metode ini.Perhatikan bahwa solusi ini tidak menangani Unicode yang menggabungkan karakter dll dengan benar, karena "Les Mise \ u0301rables" akan dikonversi menjadi "selbarésiM seL". The jawaban yang lain untuk solusi yang lebih baik.
Ini pada dasarnya menyalin karakter
input
ke string baru dan membalikkan string baru di tempat.Kenapa
string.Create
bermanfaat?Ketika kami membuat string dari array yang ada, array internal baru dialokasikan dan nilai-nilai disalin. Kalau tidak, akan mungkin untuk memutasikan string setelah pembuatannya (dalam lingkungan yang aman). Yaitu, dalam cuplikan berikut ini, kami harus mengalokasikan array dengan panjang 10 dua kali, satu sebagai buffer dan satu sebagai array internal string.
string.Create
dasarnya memungkinkan kita untuk memanipulasi array internal selama waktu pembuatan string. Ini, kita tidak perlu buffer lagi dan karena itu dapat menghindari mengalokasikan satu array char.Steve Gordon telah menulisnya secara lebih rinci di sini . Ada juga artikel tentang MSDN .
Cara menggunakan
string.Create
?Metode ini mengambil tiga parameter:
char
array internal dari string baru dan yang kedua adalah data (status) yang Anda berikanstring.Create
.Di dalam delegasi kita dapat menentukan bagaimana string baru dibuat dari data. Dalam kasus kami, kami hanya menyalin karakter dari string input ke yang
Span
digunakan oleh string baru. Kemudian kita membalikkannyaSpan
dan karenanya seluruh string dibalik.Tolak ukur
Untuk membandingkan cara saya yang diusulkan untuk membalik string dengan jawaban yang diterima, saya telah menulis dua tolok ukur menggunakan BenchmarkDotNet.
Inilah hasil di mesin saya:
Seperti yang Anda lihat, dengan
ReverseWithStringCreate
kami mengalokasikan hanya setengah dari memori yang digunakan olehReverseWithArray
metode ini.sumber
Jangan repot-repot dengan fungsi, lakukan saja di tempat. Catatan: Baris kedua akan memunculkan eksepsi argumen di jendela Immediate dari beberapa versi VS.
sumber
new string
Maaf untuk posting lama, tapi ini mungkin menarik
Hasil:
sumber
Keluaran
Untuk ukuran: 10
Untuk ukuran: 100
Untuk ukuran: 1000
Untuk ukuran: 10000
sumber
Reverse(...)
. Kalau tidak, kerja bagus.Cara termudah:
sumber
Solusi berbasis tumpukan.
Atau
sumber
Harus mengajukan contoh rekursif:
sumber
Bagaimana tentang:
sumber
ToCharArray
pertama. Enumerator LINQ juga lebih lambat dari padaArray.Reverse()
.Saya telah membuat porta C # dari Microsoft.VisualBasic.Strings . Saya tidak yakin mengapa mereka menyimpan fungsi-fungsi yang berguna (dari VB) di luar System.String in Framework, tetapi masih di bawah Microsoft.VisualBasic. Skenario yang sama untuk fungsi keuangan (misalnya
Microsoft.VisualBasic.Financial.Pmt()
).sumber
string s = "abo\u0327\u0307\u035d\U0001d166cd"
, yang berisi surato
diikuti oleh 3 menggabungkan tanda-tanda diakritik di BMP dan satu tanda menggabungkan (MUSICAL SIMBOL COMBINING STEM) dari pesawat astral (non-BMP) dan itu membuat mereka tetap utuh. Tetapi metode ini lambat jika karakter tersebut hanya muncul di akhir string panjang, karena harus pergi dua kali ke seluruh array.Maaf karena memposting di utas lama ini. Saya berlatih beberapa kode untuk wawancara.
Inilah yang saya buat untuk C #. Versi pertama saya sebelum refactoring mengerikan.
Berbeda dengan
Array.Reverse
metode di bawah ini, ini muncul lebih cepat dengan 12 karakter atau kurang di string. Setelah 13 karakter,Array.Reverse
permulaan menjadi lebih cepat, dan pada akhirnya mendominasi kecepatan. Saya hanya ingin menunjukkan kira-kira di mana kecepatan mulai berubah.Pada 100 karakter dalam string, ini lebih cepat daripada versi saya x 4. Namun, jika saya tahu bahwa string akan selalu kurang dari 13 karakter, saya akan menggunakan yang saya buat.
Pengujian dilakukan dengan
Stopwatch
dan iterasi 500.000. Juga, saya tidak yakin apakah versi saya menangani Pengganti atau situasi karakter gabungan denganUnicode
penyandian.sumber
"Cara yang lebih baik" tergantung pada apa yang lebih penting bagi Anda dalam situasi, kinerja, keanggunan, pemeliharaan, dll.
Bagaimanapun, inilah pendekatan menggunakan Array. Revers:
sumber
Jika pernah muncul dalam sebuah wawancara dan Anda diberitahu bahwa Anda tidak dapat menggunakan Array. Dibalik, saya pikir ini mungkin salah satu yang tercepat. Itu tidak membuat string baru dan hanya mengulangi lebih dari setengah dari array (yaitu O (n / 2) iterasi)
sumber
x
, atau dalam kasus Andan
, tidak digunakan. Algoritme Anda memiliki kinerjaf(x) = x + ½x + C
, di mana C adalah beberapa konstan. Karena keduanyaC
dan faktornya1½
tidak bergantung padax
, algoritma AndaO(x)
. Itu tidak berarti bahwa itu tidak akan lebih cepat untuk setiap input panjangx
, tetapi kinerjanya secara linear tergantung pada panjang input. Untuk menjawab @MarcelValdezOrozco, ya, itu jugaO(n)
, meskipun ia menyalin per potongan 16-byte untuk meningkatkan kecepatan (tidak menggunakan lurusmemcpy
pada total panjang).Jika Anda memiliki string yang hanya berisi karakter ASCII, Anda dapat menggunakan metode ini.
sumber
Pertama-tama apa yang harus Anda pahami adalah bahwa str + = akan mengubah ukuran memori string Anda untuk membuat ruang untuk 1 karakter tambahan. Ini baik-baik saja, tetapi jika Anda memiliki, katakanlah, sebuah buku dengan 1000 halaman yang ingin Anda balikkan, ini akan sangat lama untuk dieksekusi.
Solusi yang mungkin disarankan beberapa orang adalah menggunakan StringBuilder. Apa yang dilakukan pembuat string ketika Anda menjalankan + = adalah bahwa ia mengalokasikan potongan memori yang jauh lebih besar untuk menampung karakter baru sehingga tidak perlu melakukan realokasi setiap kali Anda menambahkan char.
Jika Anda benar-benar menginginkan solusi cepat dan minimal, saya sarankan yang berikut ini:
Dalam solusi ini ada satu alokasi memori awal ketika char [] diinisialisasi dan satu alokasi ketika konstruktor string membangun string dari array char.
Di sistem saya, saya menjalankan tes untuk Anda yang membalik string 2 750 000 karakter. Berikut adalah hasil untuk 10 eksekusi:
StringBuilder: kutu 190K - 200K
Array Array: 130K - 160K ticks
Saya juga menjalankan tes untuk String normal + = tetapi saya meninggalkannya setelah 10 menit tanpa output.
Namun, saya juga memperhatikan bahwa untuk string yang lebih kecil, StringBuilder lebih cepat, jadi Anda harus memutuskan implementasi berdasarkan input.
Bersulang
sumber
😀Les Misérables
sumber
sumber