Tôi có thể nhân nhiều số một chuỗi (trong C #) không?


136

Giả sử tôi có một chuỗi, ví dụ,

string snip =  "</li></ul>";

Về cơ bản tôi muốn viết nó nhiều lần, tùy thuộc vào một số giá trị nguyên.

string snip =  "</li></ul>";
int multiplier = 2;

// TODO: magic code to do this 
// snip * multiplier = "</li></ul></li></ul>";

EDIT: Tôi biết tôi có thể dễ dàng viết hàm riêng của mình để thực hiện điều này, tôi chỉ tự hỏi liệu có một toán tử chuỗi kỳ lạ nào mà tôi không biết về


Câu trả lời:


222

Trong .NET 4 bạn có thể làm điều này:

String.Concat(Enumerable.Repeat("Hello", 4))

9
Và nó không còn nhiều nữa trong .NET 3.5: String.Concat (Enumerable.Repeat ("Hello", 4) .ToArray ())
Mark Foreman

4
Tôi không nghĩ nó thanh lịch chút nào. Trong python, mã để làm điều này là: snip * số nhân (Nó không kinh khủng .. nhưng nó cũng không đẹp).
con nhím mất trí

7
@dementedhedgeoose Tôi biết bạn thừa nhận chứng mất trí của chính mình, nhưng thậm chí đau khổ như bạn, bạn có thể thấy rằng một ví dụ Python sẽ không có câu trả lời rất hay cho câu hỏi C # ... Tôi nghĩ rằng hầu hết chúng ta đều có thể thấy lựa chọn ngôn ngữ đó luôn là một sự thỏa hiệp và hầu như bất kỳ câu trả lời nào cho bất kỳ câu hỏi nào đều có thể được chú ý bằng cách vận động, dù là ủng hộ hay phản đối.
Will Dean

1
@will dean: Tôi chỉ đề cập đến tuyên bố của Matthew Nichols về sự thanh lịch của mã bạn có ở đó. Theo như tôi có thể nói mã của bạn là thanh lịch cho C #, vì hiện tại nó là viết tắt của vấn đề này. Điểm tôi đang cố gắng thực hiện là: (tôi tin) sẽ rất dễ dàng (đối với microsoft, vì các chuỗi được niêm phong) để mở rộng C # để quá tải toán tử * để cho phép nhân chuỗi int *. Mà sau đó sẽ thực sự thanh lịch trong một số ý nghĩa phổ quát, imho, không chỉ thanh lịch trong bối cảnh các ràng buộc áp đặt bởi C # như nó tồn tại vào lúc này.
con nhím mất trí

@dementedhedgeoose Đối với tôi, điều đó đi ngược lại với những gì nhị phân operator*đại diện. Để mỗi người của họ, tôi đoán.
TEK

99

Lưu ý rằng nếu "chuỗi" của bạn chỉ là một ký tự đơn, thì có quá tải của hàm tạo chuỗi để xử lý nó:

int multipler = 10;
string TenAs = new string ('A', multipler);

Điều này thực sự chuyên nghiệp.
Zaven Zareyan

61

Thật không may / may mắn thay, lớp chuỗi được niêm phong để bạn không thể kế thừa từ nó và làm quá tải toán tử *. Bạn có thể tạo một phương thức mở rộng mặc dù:

public static string Multiply(this string source, int multiplier)
{
   StringBuilder sb = new StringBuilder(multiplier * source.Length);
   for (int i = 0; i < multiplier; i++)
   {
       sb.Append(source);
   }

   return sb.ToString();
}

string s = "</li></ul>".Multiply(10);

5
Chỉ là nơi tôi đang đi! Bạn có thể có thể tối ưu hóa bằng cách sử dụng hệ số nhân. Độ dài * trong trình tạo StringBuilder
Marc Gravell

2
Nhận xét của Marc chỉ là nơi tôi sẽ đến :)
Jon Skeet

1
Bạn cần (nguồn. Độ dài * số nhân), không chỉ (số nhân)
Marc Gravell

1
Rất chắc chắn. Nó phân bổ một chuỗi (có độ dài đó) đằng sau hậu trường, sau đó biến đổi nó. Nó không hoạt động như một Danh sách thông thường <T>, v.v.
Marc Gravell

1
Phương pháp mở rộng là lý tưởng ở đây.
Chris Ballance

12

Tôi với DrJokepu về điều này , nhưng nếu vì lý do nào đó bạn muốn gian lận bằng chức năng tích hợp thì bạn có thể làm một cái gì đó như thế này:

string snip = "</li></ul>";
int multiplier = 2;

string result = string.Join(snip, new string[multiplier + 1]);

Hoặc, nếu bạn đang sử dụng .NET 4:

string result = string.Concat(Enumerable.Repeat(snip, multiplier));

Cá nhân tôi sẽ không bận tâm - một phương pháp mở rộng tùy chỉnh đẹp hơn nhiều.


1
Tôi không bao giờ biết có một gian lận như thế này. =)
Jronny

10

Chỉ vì mục đích hoàn chỉnh - đây là một cách khác để làm điều này:

public static string Repeat(this string s, int count)
{
    var _s = new System.Text.StringBuilder().Insert(0, s, count).ToString();
    return _s;
}

Tôi nghĩ rằng tôi đã lấy cái đó từ Stack Overflow một thời gian trước, vì vậy đó không phải là ý tưởng của tôi.


9

Bạn sẽ phải viết một phương thức - tất nhiên, với C # 3.0, nó có thể là một phương thức mở rộng:

public static string Repeat(this string, int count) {
    /* StringBuilder etc */ }

sau đó:

string bar = "abc";
string foo = bar.Repeat(2);

Ngay cả .NET3 cũng không có En.Rable.
Will Dean

@ Will - .NET 3 là WCF / WPF, v.v. nó tồn tại trong .NET 3.5, nhưng sau đó bạn cũng cần string.Joinnó - tại sao không chỉ lặp lại n lần? Trực tiếp hơn nhiều.
Marc Gravell

Cảm ơn - Tôi đã không nghĩ đúng về 3.0 so với 3.5. Tại sao không chỉ sử dụng một vòng lặp, chắc chắn đó là toàn bộ bản chất của cuộc tranh luận về chức năng và mệnh lệnh? Tôi đã đăng một câu trả lời .net 4 xuống thấp hơn mà tôi nghĩ không quá tệ trong cuộc tranh luận về 'sự thông minh chức năng' so với 'sự rõ ràng lặp đi lặp lại'.
Will Dean

8

Hơi muộn một chút (và chỉ để giải trí), nếu bạn thực sự muốn sử dụng *toán tử cho công việc này, bạn có thể làm điều này:

public class StringWrap
{
    private string value;
    public StringWrap(string v)
    {
        this.value = v;
    }
    public static string operator *(StringWrap s, int n)
    {
        return s.value.Multiply(n); // DrJokepu extension
    }
}

Và vì thế:

var newStr = new StringWrap("TO_REPEAT") * 5;

Lưu ý rằng, miễn là bạn có thể tìm thấy một hành vi hợp lý cho họ, bạn cũng có thể xử lý các nhà khai thác khác thông qua StringWraplớp, giống như \, ^, %vv ...

Tái bút

Multiply()tín dụng mở rộng cho @DrJokepu tất cả các quyền ;-)


7

Điều này ngắn gọn hơn nhiều:

new StringBuilder().Insert(0, "</li></ul>", count).ToString()

Không gian tên using System.Text;nên được nhập trong trường hợp này.


2
string Multiply(string input, int times)
{
     StringBuilder sb = new StringBuilder(input.length * times);
     for (int i = 0; i < times; i++)
     {
          sb.Append(input);
     }
     return sb.ToString();
}

2

Nếu bạn có .Net 3.5 nhưng không phải 4.0, bạn có thể sử dụng System.Linq's

String.Concat(Enumerable.Range(0, 4).Select(_ => "Hello").ToArray())

Để có được một chuỗi bạn vẫn cần String.Concat, và trên 3.5 bạn cũng cần .ToArray(). Không phải là giải pháp thanh lịch nhất, tôi sợ.
Kobi

2

Vì mọi người đang thêm các ví dụ .NET4 / Linq của riêng họ, tôi cũng có thể thêm các ví dụ của riêng mình. (Về cơ bản, đó là DrJokepu, được rút gọn thành một lớp lót)

public static string Multiply(this string source, int multiplier) 
{ 
    return Enumerable.Range(1,multiplier)
             .Aggregate(new StringBuilder(multiplier*source.Length), 
                   (sb, n)=>sb.Append(source))
             .ToString();
}

0

Được rồi, đây là vấn đề của tôi:

public static class ExtensionMethods {
  public static string Multiply(this string text, int count)
  {
    return new string(Enumerable.Repeat(text, count)
      .SelectMany(s => s.ToCharArray()).ToArray());
  }
}

Tất nhiên tôi hơi ngớ ngẩn, nhưng khi tôi cần lập bảng trong các lớp tạo mã, Enumerable.Repeat sẽ làm điều đó cho tôi. Và vâng, phiên bản StringBuilder cũng tốt.


0

Đây là của tôi về điều này chỉ để tham khảo trong tương lai:

    /// <summary>
    /// Repeats a System.String instance by the number of times specified;
    /// Each copy of thisString is separated by a separator
    /// </summary>
    /// <param name="thisString">
    /// The current string to be repeated
    /// </param>
    /// <param name="separator">
    /// Separator in between copies of thisString
    /// </param>
    /// <param name="repeatTimes">
    /// The number of times thisString is repeated</param>
    /// <returns>
    /// A repeated copy of thisString by repeatTimes times 
    /// and separated by the separator
    /// </returns>
    public static string Repeat(this string thisString, string separator, int repeatTimes) {
        return string.Join(separator, ParallelEnumerable.Repeat(thisString, repeatTimes));
    }

Tôi hy vọng bạn không thực sự sử dụng ParallelEnumerabletrong các tình huống như thế này. string.Joincần phải sử dụng các yếu tố theo thứ tự, do đó, song song thế hệ của chúng là không được phép.
Gabe

@Gabe: Vì các mặt hàng giống nhau và thực sự chỉ là bản sao của ThisString, nên tôi không cần phải lo lắng về việc đặt hàng ở đây, tôi đoán vậy.
Jronny

Tôi đồng ý với nhiều giáo viên trong lĩnh vực rằng việc viết mã để nói những gì bạn muốn nói là điều tốt. Không có ích gì để nói rằng bạn muốn điều này song song và chỉ thầm nghĩ "Chà, tôi biết nó sẽ không song song trong trường hợp cụ thể này"
sehe

Tôi nghĩ làm cho nó song song làm cho nó nhanh hơn, hoặc xin vui lòng khai sáng cho tôi. Đó là lý do tại sao tôi chuyển đổi nó thành ParallelEnumerable, vì vậy tôi nghĩ rằng tôi viết mã để nói những gì tôi muốn nói ... Cảm ơn.
Jronny
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.