Cara terbaik untuk mengulangi karakter dalam C #

815

Apa itu cara terbaik untuk menghasilkan string \t's di C #

Saya belajar C # dan bereksperimen dengan berbagai cara untuk mengatakan hal yang sama.

Tabs(uint t)adalah fungsi yang mengembalikan sebuah stringdengan tjumlah \t's

Misalnya Tabs(3)pengembalian"\t\t\t"

Manakah dari tiga cara penerapan Tabs(uint numTabs)ini yang terbaik?

Tentu saja itu tergantung pada apa artinya "terbaik".

  1. Versi LINQ hanya dua baris, yang bagus. Tetapi apakah panggilan untuk Berulang dan Agregat yang tidak perlu menghabiskan waktu / sumber daya?

  2. The StringBuilderVersi ini sangat jelas, tetapi adalah StringBuilderkelas entah bagaimana lebih lambat?

  3. The stringversi dasar, yang berarti mudah dimengerti.

  4. Tidak masalah sama sekali? Apakah mereka semua sama?

Ini semua pertanyaan untuk membantu saya merasakan C # yang lebih baik.

private string Tabs(uint numTabs)
{
    IEnumerable<string> tabs = Enumerable.Repeat("\t", (int) numTabs);
    return (numTabs > 0) ? tabs.Aggregate((sum, next) => sum + next) : ""; 
}  

private string Tabs(uint numTabs)
{
    StringBuilder sb = new StringBuilder();
    for (uint i = 0; i < numTabs; i++)
        sb.Append("\t");

    return sb.ToString();
}  

private string Tabs(uint numTabs)
{
    string output = "";
    for (uint i = 0; i < numTabs; i++)
    {
        output += '\t';
    }
    return output; 
}
Alex Baranosky
sumber

Jawaban:

1492

Bagaimana dengan ini:

string tabs = new String('\t', n);

Di mana nberapa kali Anda ingin mengulangi string.

Atau lebih baik:

static string Tabs(int n)
{
    return new String('\t', n);
}
CMS
sumber
2
apakah ada cara untuk mengulangi ini untuk sebuah kata alih-alih menggunakan '\ t' cara menggunakan "waktu"
asdfkjasdfjk
6
@ user1478137 Atau, lebih baik (juga lebih jauh ke bawah): ini
Xynariz
161
string.Concat(Enumerable.Repeat("ab", 2));

Kembali

"abab"

Dan

string.Concat(Enumerable.Repeat("a", 2));

Kembali

"A A"

dari...

Apakah ada fungsi bawaan untuk mengulang string atau char di .net?

Carter Medlin
sumber
1
Buat lebih baik dengan melakukannya tanpa Linq dan dengan StruingBuilder!
Bitterblue
4
'' StringBuilder '' belum tentu lebih cepat stackoverflow.com/questions/585860/…
Schiavini
6
Ini mungkin tidak lebih cepat, tetapi dapat menghemat alokasi memori (tekanan) jika Anda menentukan kapasitas yang benar di depan, dan itu bisa sama pentingnya dengan tolok ukur mikro untuk membuat profil ini.
wekempf
1
var strRepeat = string.Concat (Enumerable.Repeat ("ABC", 1000000)); // 50ms
yongfa365
1
@Pharap string.Joinlebih cepat dalam contoh karena mereka menggunakan pembatas ruang. string.Concatsesuai ketika tidak ada pembatas.
Carter Medlin
124

Di semua versi .NET, Anda dapat mengulangi string dengan demikian:

public static string Repeat(string value, int count)
{
    return new StringBuilder(value.Length * count).Insert(0, value, count).ToString();
}

Untuk mengulangi karakter, new String('\t', count)adalah taruhan terbaik Anda. Lihat jawabannya oleh @CMS .

Binoj Antony
sumber
7
Sejauh ini, ini adalah kinerja tercepat untuk String. Metode lain membuat overhead terlalu banyak.
midspace
@ ruang tengah Apakah Anda tahu ada yang menjelaskan mengapa jawaban lain lebih buruk? Saya akan mengasumsikan String.Compat asli akan dioptimalkan secara internal seperti halnya StringBuilder
Marie
@Marie Artikel berikut menjelaskan beberapa kelebihan. support.microsoft.com/en-au/help/306822/... Jika tidak ada dua faktor lain, StringBuilder memungkinkan string dan tidak terbatas hanya pada char (meskipun itu tidak berkaitan dengan pertanyaan asli), dan string. Jawaban ringkas di atas harus membuat array terlebih dahulu menggunakan Enumerable.Repeat. Seperti yang saya katakan, itu tidak perlu di atas kepala.
midspace
Saya berasumsi itu tidak akan membuat array terlebih dahulu karena itu bisa saja beralih item demi item. Terima kasih atas tautannya, saya akan membacanya!
Marie
63

Versi terbaik tentu menggunakan cara bawaan:

string Tabs(int len) { return new string('\t', len); }

Dari solusi lain, lebih suka yang termudah; hanya jika ini terbukti terlalu lambat, upayakan solusi yang lebih efisien.

Jika Anda menggunakan a StringBuilderdan mengetahui panjangnya yang dihasilkan sebelumnya, kemudian juga menggunakan konstruktor yang sesuai, ini jauh lebih efisien karena itu berarti hanya satu alokasi waktu yang memakan waktu, dan tidak perlu menyalin data. Omong kosong: tentu saja kode di atas lebih efisien.

Konrad Rudolph
sumber
12
sb.Append ('\ t', len);
dan-gph
7
Tolok ukur saya menunjukkan new string('\t', len)antara 2x dan 7x lebih cepat dari StringBuilderpendekatan. Menurut Anda mengapa StringBuilderlebih efisien dalam hal ini?
StriplingWarrior
6
@ TriplingWarrior Terima kasih telah memperbaiki ini (setelah itu berdiri di sini selama dua tahun, tidak kurang!).
Konrad Rudolph
51

Metode ekstensi:

public static string Repeat(this string s, int n)
{
    return new String(Enumerable.Range(0, n).SelectMany(x => s).ToArray());
}

public static string Repeat(this char c, int n)
{
    return new String(c, n);
}
Rodrick Chapman
sumber
39
Sekali waktu orang digunakan saat loop
prabhakaran
2
@prabhakaran Saya setuju tetapi keuntungan dari Linq adalah dalam komunikasi; itu hampir selalu sepele untuk menerapkan kembali ekspresi Linq menggunakan konstruksi imperatif.
Rodrick Chapman
10
Enumerable.Range(0, n).SelectMany(x => s)bisa diganti dengan yang sederhana Enumerable.Repeat(s, n).
Palec
5
@Palec Tidak, tidak bisa. The SelectManykehendak untuk setiap boneka tunggal xmemberikan urutan charnilai (sejak string salat IEnumerable<char>), dan semua orang charurutan yang bersambung ke satu panjang charberurutan. Apa yang Anda sarankan sebagai gantinya akan memberikan IEnumerable<string>. Itu tidak sama.
Jeppe Stig Nielsen
2
Saya salah, @JeppeStigNielsen. Terimakasih atas peringatannya. Jika saya benar-benar ingin menggunakan Enumerable.Repeat, saya harus menggabungkan string bersama-sama: string.Concat(Enumerable.Repeat(s, n)). Ini sudah diposting sebelumnya .
Palec
40

Bagaimana dengan menggunakan metode ekstensi?


public static class StringExtensions
{
   public static string Repeat(this char chatToRepeat, int repeat) {

       return new string(chatToRepeat,repeat);
   }
   public  static string Repeat(this string stringToRepeat,int repeat)
   {
       var builder = new StringBuilder(repeat*stringToRepeat.Length);
       for (int i = 0; i < repeat; i++) {
           builder.Append(stringToRepeat);
       }
       return builder.ToString();
   }
}

Anda kemudian dapat menulis:

Debug.WriteLine('-'.Repeat(100)); // For Chars  
Debug.WriteLine("Hello".Repeat(100)); // For Strings

Perhatikan bahwa tes kinerja menggunakan versi stringbuilder untuk karakter sederhana alih-alih string memberi Anda hukuman dalm kinerja utama: di komputer saya perbedaan dalam kinerja yang dipalsukan adalah 1:20 antara: Debug.WriteLine ('-'. Ulangi (1000000)) // versi char dan
Debug.WriteLine ("-". Ulangi (1000000)) // versi string

Ronnie
sumber
2
Kinerja versi string dapat ditingkatkan dengan menggunakan StringBuilder.Insert(Int32, String, Int32), seperti yang dijawab Binoj Anthony .
Palec
23

Bagaimana dengan ini:

//Repeats a character specified number of times
public static string Repeat(char character,int numberOfIterations)
{
    return "".PadLeft(numberOfIterations, character);
}

//Call the Repeat method
Console.WriteLine(Repeat('\t',40));
Denys Wessels
sumber
4
haha .. itu yang bisa saya pikirkan ketika saya jatuh ke situasi ini sekali. Tetapi secara pribadi saya menemukan new string('\t', 10)solusi terbaik
shashwat
Trik ini juga digunakan dalam Essential C # 6.0 .
Programmer Berorientasi Uang
22

Saya tahu bahwa pertanyaan ini sudah berusia lima tahun tetapi ada cara sederhana untuk mengulangi string yang bahkan berfungsi di .Net 2.0.

Untuk mengulang string:

string repeated = new String('+', 3).Replace("+", "Hello, ");

Kembali

"Halo halo halo, "

Untuk mengulang string sebagai array:

// Two line version.
string repeated = new String('+', 3).Replace("+", "Hello,");
string[] repeatedArray = repeated.Split(',');

// One line version.
string[] repeatedArray = new String('+', 3).Replace("+", "Hello,").Split(',');

Kembali

{"Halo halo halo", ""}

Tetap sederhana.

ChaimG
sumber
19

Katakanlah Anda ingin mengulangi '\ t' n beberapa kali, Anda dapat menggunakan;

String.Empty.PadRight(n,'\t')
Amin
sumber
1
Terima kasih. Ini juga sangat cepat. codereview.stackexchange.com/questions/36391/…
Sunsetquest
Saya selalu melakukannya dengan cara ini. Bahkan jika dibungkus dengan metode ekstensi itu lebih sederhana daripada implementasi lain yang diposting di sini. Perhatikan bahwa OP hanya ingin mengulang \ t, bukan string.
Michael Pita
17

Contoh pertama Anda yang menggunakan Enumerable.Repeat:

private string Tabs(uint numTabs)
{
    IEnumerable<string> tabs = Enumerable.Repeat(
                                 "\t", (int) numTabs);
    return (numTabs > 0) ? 
            tabs.Aggregate((sum, next) => sum + next) : ""; 
} 

dapat ditulis ulang dengan lebih kompak dengan String.Concat:

private string Tabs(uint numTabs)
{       
    return String.Concat(Enumerable.Repeat("\t", (int) numTabs));
}
sinar
sumber
14

Menggunakan String.Concatdan Enumerable.Repeatmana yang akan lebih murah daripada menggunakanString.Join

public static Repeat(this String pattern, int count)
{
    return String.Concat(Enumerable.Repeat(pattern, count));
}
bradgonesurfing
sumber
9
var str = new string(Enumerable.Repeat('\t', numTabs).ToArray());
wb
sumber
4

Jawabannya sangat tergantung pada kompleksitas yang Anda inginkan. Misalnya, saya ingin menguraikan semua indentasi saya dengan bilah vertikal, jadi string indentasi saya ditentukan sebagai berikut:

return new string(Enumerable.Range(0, indentSize*indent).Select(
  n => n%4 == 0 ? '|' : ' ').ToArray());
Dmitri Nesteruk
sumber
3

Namun metode lain

new System.Text.StringBuilder().Append('\t', 100).ToString()
Artyom
sumber
Melewati panjang string yang dihasilkan ke StringBuilderkonstruktor menyimpan realokasi. Namun, ini lebih cerewet dan kurang efisien daripada menggunakan stringkonstruktor yang dapat mengulangi karakter yang diberikan, seperti yang sudah ditunjukkan dalam jawaban yang diterima.
Palec
3

Bagi saya tidak masalah:

public static class Utils
{
    public static string LeftZerosFormatter(int zeros, int val)
    {
        string valstr = val.ToString();

        valstr = new string('0', zeros) + valstr;

        return valstr.Substring(valstr.Length - zeros, zeros);
    }
}
Ibngel Ibáñez
sumber
2

Anda dapat membuat metode ekstensi

static class MyExtensions
{
    internal static string Repeat(this char c, int n)
    {
        return new string(c, n);
    }
}

Maka Anda bisa menggunakannya seperti ini

Console.WriteLine('\t'.Repeat(10));
ivan
sumber
1

Tanpa ragu jawaban yang diterima adalah cara terbaik dan tercepat untuk mengulang satu karakter.

Jawaban Binoj Anthony adalah cara yang sederhana dan cukup efisien untuk mengulang sebuah string.

Namun, jika Anda tidak keberatan sedikit kode lagi, Anda dapat menggunakan teknik isi array saya untuk secara efisien membuat string ini lebih cepat. Dalam tes perbandingan saya, kode di bawah ini dijalankan sekitar 35% dari waktu kode StringBuilder.Insert.

public static string Repeat(this string value, int count)
{
    var values = new char[count * value.Length];
    values.Fill(value.ToCharArray());
    return new string(values);
}

public static void Fill<T>(this T[] destinationArray, params T[] value)
{
    if (destinationArray == null)
    {
        throw new ArgumentNullException("destinationArray");
    }

    if (value.Length > destinationArray.Length)
    {
        throw new ArgumentException("Length of value array must not be more than length of destination");
    }

    // set the initial array value
    Array.Copy(value, destinationArray, value.Length);

    int copyLength, nextCopyLength;

    for (copyLength = value.Length; (nextCopyLength = copyLength << 1) < destinationArray.Length; copyLength = nextCopyLength)
    {
        Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength);
    }

    Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength);
}

Untuk lebih lanjut tentang teknik pengisian array ini, lihat Cara tercepat untuk mengisi array dengan nilai tunggal

Grax32
sumber
0

Coba ini:

  1. Tambahkan referensi Microsoft.VisualBasic
  2. Gunakan: String result = Microsoft.VisualBasic.Strings.StrDup (5, "hai");
  3. Beri tahu saya jika itu berhasil untuk Anda.
Toso Pankovski
sumber
Menambahkan ketergantungan pada rakitan lain dan kebutuhan untuk memuatnya tidak masuk akal dalam kebanyakan kasus ketika Anda membutuhkan fungsi tersebut. Namun, senang mengetahui ada hal seperti itu di .NET.
Palec
Ada banyak pro dan kontra dalam konteks yang berbeda, jadi setiap orang harus memutuskan tergantung pada situasi di mana dia berada.
Toso Pankovski
-1

Meskipun sangat mirip dengan saran sebelumnya, saya ingin membuatnya tetap sederhana dan menerapkan yang berikut:

string MyFancyString = "*";
int strLength = 50;
System.Console.WriteLine(MyFancyString.PadRight(strLength, "*");

Standar. Net,

Gemuk
sumber
Itu hanya akan menambah padding, jangan ulangi
levi