Cách tốt nhất để lặp lại một nhân vật trong C #


814

Cách tốt nhất để tạo một chuỗi \ttrong C # là gì

Tôi đang học C # và thử nghiệm nhiều cách khác nhau để nói cùng một điều.

Tabs(uint t)là một hàm trả về một stringvới tsố lượng \t's

Ví dụ Tabs(3)trả về"\t\t\t"

Cách nào trong ba cách thực hiện Tabs(uint numTabs)này là tốt nhất?

Tất nhiên điều đó phụ thuộc vào "tốt nhất" nghĩa là gì.

  1. Phiên bản LINQ chỉ có hai dòng, rất hay. Nhưng các cuộc gọi để Lặp lại và Tổng hợp tiêu tốn thời gian / tài nguyên không cần thiết?

  2. Các StringBuilderphiên bản là rất rõ ràng nhưng là StringBuilderlớp bằng cách nào đó chậm hơn?

  3. Các stringphiên bản cơ bản, có nghĩa là nó là dễ hiểu.

  4. Nó không quan trọng chút nào? Có phải tất cả đều bình đẳng?

Đây là tất cả các câu hỏi để giúp tôi cảm nhận tốt hơn về C #.

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; 
}

Câu trả lời:


1491

Cái này thì sao:

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

Trong trường hợp nlà số lần bạn muốn lặp lại chuỗi.

Hoặc tốt hơn:

static string Tabs(int n)
{
    return new String('\t', n);
}

2
Có cách nào để lặp lại điều này cho một từ? thay vì sử dụng '\ t' cách sử dụng "thời gian"
asdfkjasdfjk

6
@ user1478137 Hoặc, tốt hơn (cũng tiếp tục xuống): này
Xynariz

161
string.Concat(Enumerable.Repeat("ab", 2));

Trả về

"abab"

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

Trả về

"aa"

từ...

Có một hàm dựng sẵn để lặp lại chuỗi hoặc char trong .net không?


1
Làm cho nó tốt hơn bằng cách làm nó mà không có Linq và với StruingBuilder!
Bitterblue

4
'' StringBuilder '' không nhất thiết phải là stackoverflow.com/questions/585860/
triệt

6
Nó có thể không nhanh hơn, nhưng nó có thể tiết kiệm phân bổ bộ nhớ (áp lực) nếu bạn chỉ định dung lượng chính xác lên phía trước, và điều đó có thể quan trọng như điểm chuẩn vi mô của cấu hình này.
wekempf

1
var strRepeat = string.Concat (En đếmable.Repeat ("ABC", 1000000)); // 50ms
yongfa365

1
@Pharap string.Jointrong ví dụ nhanh hơn vì họ đang sử dụng dấu phân cách không gian. string.Concatlà thích hợp khi không có dấu phân cách.
Carter Medlin

124

Trong tất cả các phiên bản .NET, bạn có thể lặp lại một chuỗi như vậy:

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

Để lặp lại một nhân vật, new String('\t', count)là đặt cược tốt nhất của bạn. Xem câu trả lời của @CMS .


7
Đây là hiệu suất nhanh nhất cho String. Các phương pháp khác tạo ra quá nhiều chi phí.
gian giữa

@midspace Bạn có biết nếu có ai giải thích tại sao các câu trả lời khác tệ hơn không? Tôi đã giả sử String.Concat bản địa sẽ được tối ưu hóa nội bộ như StringBuilder
Marie

@Marie Bài viết sau đây giải thích một số giá trị. support.microsoft.com/en-au/help/306822/. Nếu không, hai yếu tố khác là StringBuilder cho phép các chuỗi và không giới hạn chỉ là một char (mặc dù điều đó không liên quan đến câu hỏi ban đầu) và chuỗi. Câu trả lời concat ở trên phải tạo ra một mảng đầu tiên bằng cách sử dụng Enumerable.Repeat. Như tôi đã nói, đó là chi phí không cần thiết.
khoảng giữa

Tôi đã giả định rằng nó sẽ không tạo ra một mảng đầu tiên bởi vì nó chỉ có thể lặp lại từng mục. Cảm ơn bạn đã liên kết, tôi sẽ đọc nó!
Marie

63

Phiên bản tốt nhất chắc chắn là sử dụng cách dựng sẵn:

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

Trong số các giải pháp khác, thích dễ nhất; chỉ khi điều này được chứng minh là quá chậm, hãy phấn đấu cho một giải pháp hiệu quả hơn.

Nếu bạn sử dụng a StringBuildervà biết trước độ dài kết quả của nó, thì cũng sử dụng một hàm tạo thích hợp, điều này sẽ hiệu quả hơn nhiều vì điều đó có nghĩa là chỉ có một phân bổ tốn thời gian và không sao chép dữ liệu không cần thiết. Vô nghĩa: tất nhiên đoạn mã trên hiệu quả hơn.


12
sb.Append ('\ t', len);
dan-gph

7
Điểm chuẩn của tôi đang hiển thị new string('\t', len)nhanh hơn từ 2 đến 7 lần so với StringBuilderphương pháp tiếp cận. Tại sao bạn nghĩ StringBuilderlà hiệu quả hơn trong trường hợp này?
StriplingWar Warrior

6
@StriplingWar Warrior Cảm ơn bạn đã sửa lỗi này (sau khi nó đã đứng ở đây được hai năm, không hơn không kém!).
Konrad Rudolph

51

Phương pháp mở rộng:

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

39
Ngày xửa ngày xưa người ta dùng vòng lặp
prabhakaran

2
@prabhakaran Tôi đồng ý nhưng lợi thế của Linq là trong giao tiếp; hầu như luôn luôn tầm thường để thực hiện lại biểu thức Linq bằng cách sử dụng các cấu trúc bắt buộc.
Rodrick Chapman

10
Enumerable.Range(0, n).SelectMany(x => s)có thể được thay thế bằng một đơn giản Enumerable.Repeat(s, n).
Palec

5
@Palec Không thể. Ý SelectManychí cho mỗi hình nộm đơn xđưa ra một chuỗi các chargiá trị (kể từ khi string sthực hiện IEnumerable<char>) và tất cả các charchuỗi đó được nối với một charchuỗi dài . Những gì bạn đề nghị thay vào đó sẽ cung cấp cho một IEnumerable<string>. Nó không giống nhau.
Jeppe Stig Nielsen

2
Tôi đã sai, @JeppeStigNielsen. Cảm ơn cho những người đứng đầu lên. Nếu tôi thực sự muốn sử dụng Enumerable.Repeat, tôi sẽ phải nối các chuỗi lại với nhau : string.Concat(Enumerable.Repeat(s, n)). Điều này đã được đăng trước đó .
Palec

40

Còn việc sử dụng phương pháp mở rộng thì sao?


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

Sau đó bạn có thể viết:

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

Lưu ý rằng một bài kiểm tra hiệu năng của việc sử dụng phiên bản tạo chuỗi cho các ký tự đơn giản thay vì chuỗi cung cấp cho bạn một mức độ chính xác: trên máy tính của tôi, sự khác biệt về hiệu suất được đưa ra là 1:20 giữa: Debug.WriteLine ('-'. Lặp lại (1000000)) // phiên bản char và
Debug.WriteLine ("-". Lặp lại (1000000)) // phiên bản chuỗi


2
Hiệu suất của phiên bản chuỗi có thể được cải thiện bằng cách sử dụng StringBuilder.Insert(Int32, String, Int32), như Binoj Anthony đã trả lời .
Palec

23

Còn cái này thì sao:

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

4
haha .. đó là những gì tôi có thể nghĩ đến khi tôi rơi vào tình huống này một lần. Nhưng cá nhân tôi thấy đó new string('\t', 10)là giải pháp tốt nhất
shashwat

Thủ thuật này cũng được sử dụng trong Essential C # 6.0 .
Lập trình viên định hướng tiền

22

Tôi biết rằng câu hỏi này đã được năm tuổi nhưng có một cách đơn giản để lặp lại một chuỗi thậm chí hoạt động trong .Net 2.0.

Để lặp lại một chuỗi:

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

Trả về

"Xin chào xin chào xin chào, "

Để lặp lại một chuỗi dưới dạng một mảng:

// 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(',');

Trả về

{"Xin chào xin chào xin chào", ""}

Giữ cho nó đơn giản.


19

Giả sử bạn muốn lặp lại số lần, bạn có thể sử dụng;

String.Empty.PadRight(n,'\t')

1
Cảm ơn. Điều này cũng rất nhanh. codereview.stackexchange.com/questions/36391/NH
Sunsetquest

Tôi đã luôn luôn làm theo cách này. Ngay cả khi được gói trong một phương thức mở rộng, nó vẫn đơn giản hơn các triển khai khác được đăng ở đây. Lưu ý rằng OP chỉ muốn lặp lại \ t, không phải chuỗi.
Michael Ruy băng

17

Ví dụ đầu tiên của bạn sử dụng Enumerable.Repeat:

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

có thể được viết lại gọn hơn với String.Concat:

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

14

Sử dụng String.ConcatEnumerable.Repeatsẽ ít tốn kém hơn so với sử dụngString.Join

public static Repeat(this String pattern, int count)
{
    return String.Concat(Enumerable.Repeat(pattern, count));
}

9
var str = new string(Enumerable.Repeat('\t', numTabs).ToArray());

4

Câu trả lời thực sự phụ thuộc vào sự phức tạp mà bạn muốn. Ví dụ: tôi muốn phác thảo tất cả các thụt lề của mình bằng một thanh dọc, vì vậy chuỗi thụt lề của tôi được xác định như sau:

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

3

Và một phương pháp khác

new System.Text.StringBuilder().Append('\t', 100).ToString()

Truyền chiều dài chuỗi kết quả cho hàm StringBuildertạo sẽ tiết kiệm phân bổ lại. Tuy nhiên, điều này là trò chuyện nhiều hơn và kém hiệu quả hơn so với việc sử dụng hàm stringtạo có thể lặp lại một ký tự đã cho, như đã được hiển thị trong câu trả lời được chấp nhận.
Palec

3

Đối với tôi là tốt:

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

2

Bạn có thể tạo một phương thức mở rộng

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

Sau đó, bạn có thể sử dụng nó như thế này

Console.WriteLine('\t'.Repeat(10));

1

Không nghi ngờ gì, câu trả lời được chấp nhận là cách tốt nhất và nhanh nhất để lặp lại một ký tự.

Câu trả lời của Binoj Anthony là một cách đơn giản và khá hiệu quả để lặp lại một chuỗi.

Tuy nhiên, nếu bạn không bận tâm thêm một chút mã, bạn có thể sử dụng kỹ thuật điền mảng của tôi để tạo các chuỗi này nhanh hơn. Trong các thử nghiệm so sánh của tôi, mã bên dưới đã thực thi trong khoảng 35% thời gian của mã 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);
}

Để biết thêm về kỹ thuật điền mảng này, hãy xem Cách nhanh nhất để điền vào một mảng với một giá trị duy nhất


0

Thử cái này:

  1. Thêm tài liệu tham khảo Microsoft.VisualBasic
  2. Sử dụng: Chuỗi kết quả = Microsoft.VisualBasic.Strings.StrDup (5, "hi");
  3. Hãy cho tôi biết nếu nó làm việc cho bạn.

Thêm sự phụ thuộc vào một hội đồng khác và nhu cầu tải nó là không hợp lý trong hầu hết các trường hợp khi bạn cần chức năng như vậy. Tuy nhiên, thật tốt khi biết có một điều như vậy trong .NET.
Palec

Có nhiều ưu và nhược điểm trong các bối cảnh khác nhau, vì vậy mọi người nên quyết định tùy thuộc vào tình huống cô ấy / anh ấy đang ở.
Toso Pankovski

-1

Mặc dù rất giống với một đề nghị trước đây, tôi muốn giữ cho nó đơn giản và áp dụng như sau:

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

Tiêu chuẩn .Net thực sự,


Nó sẽ chỉ thêm phần đệm, không lặp lại
levi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.