Есть ли простой способ вернуть строку, повторенную X раз?

Я пытаюсь вставить определенное количество отступов перед строкой на основе глубины элементов, и мне интересно, есть ли способ вернуть строку, повторяющуюся X раз. Пример:

string indent = "---";
Console.WriteLine(indent.Repeat(0)); //would print nothing.
Console.WriteLine(indent.Repeat(1)); //would print "---".
Console.WriteLine(indent.Repeat(2)); //would print "------".
Console.WriteLine(indent.Repeat(3)); //would print "---------".

Ответ 2

Если вы используете .NET 4.0, вы можете использовать string.Concat вместе с Enumerable.Repeat.

int N = 5; // or whatever
Console.WriteLine(string.Concat(Enumerable.Repeat(indent, N)));

В противном случае я бы пошел с чем-то вроде Adam answer.

Причина, по которой я вообще не советую использовать ответ Andrey, просто состоит в том, что вызов ToArray() вводит лишние накладные расходы, которых можно избежать с помощью подхода StringBuilder, предложенного Адам. Тем не менее, по крайней мере, он работает без требования .NET 4.0; и это быстро и просто (и не собирается убивать вас, если эффективность не слишком важна).

Ответ 3

public static class StringExtensions
{
    public static string Repeat(this string input, int count)
    {
        if (!string.IsNullOrEmpty(input))
        {
            StringBuilder builder = new StringBuilder(input.Length * count);

            for(int i = 0; i < count; i++) builder.Append(input);

            return builder.ToString();
        }

        return string.Empty;
    }
}

Ответ 4

наиболее эффективное решение для строки

string result = new StringBuilder().Insert(0, "---", 5).ToString();

Ответ 5

Используйте String.PadLeft, если ваша нужная строка содержит только один char.

public static string Indent(int count, char pad)
{
    return String.Empty.PadLeft(count, pad);
}

Кредит здесь

Ответ 6

Для многих сценариев это, вероятно, самое подходящее решение:

public static class StringExtensions
{
    public static string Repeat(this string s, int n)
        => new StringBuilder(s.Length * n).Insert(0, s, n).ToString();
}

Использование тогда:

text = "Hello World! ".Repeat(5);

Это основано на других ответах (особенно @c0rd's). Помимо простоты, он обладает следующими особенностями, которые разделяют не все другие обсуждаемые методы:

  • Повторение строки любой длины, а не просто символа (согласно запросу OP).
  • Эффективное использование StringBuilder благодаря предварительному распределению памяти.

Ответ 7

Я бы пошёл за Дэном Тао, но если вы не используете .NET 4.0, вы можете сделать что-то вроде этого:

public static string Repeat(this string str, int count)
{
    return Enumerable.Repeat(str, count)
                     .Aggregate(
                        new StringBuilder(),
                        (sb, s) => sb.Append(s))
                     .ToString();
}

Ответ 8

Вы можете повторить вашу строку (если это не один символ) и объединить результат, например так:

String.Concat(Enumerable.Repeat("---", 5))

Ответ 9

        string indent = "---";
        string n = string.Concat(Enumerable.Repeat(indent, 1).ToArray());
        string n = string.Concat(Enumerable.Repeat(indent, 2).ToArray());
        string n = string.Concat(Enumerable.Repeat(indent, 3).ToArray());

Ответ 10

Мне нравится ответ. В то же время строки, которые я использовал в прошлом:

"" PadLeft (3 * Отступ, '-').

Это выполнит создание отступа, но технически вопрос состоял в том, чтобы повторить строку. Если отступ строки является чем-то вроде > - < то это, а также принятый ответ не сработает. В этом случае решение c0rd с использованием stringbuilder выглядит хорошо, хотя накладные расходы на построитель строк могут фактически не сделать его наиболее эффективным. Один из вариантов состоит в том, чтобы построить массив строк, заполнить его строками с отступом, а затем выполнить это. Для whit:

int Indent = 2;

string[] sarray = new string[6];  //assuming max of 6 levels of indent, 0 based

for (int iter = 0; iter < 6; iter++)
{
    //using c0rd stringbuilder concept, insert ABC as the indent characters to demonstrate any string can be used
    sarray[iter] = new StringBuilder().Insert(0, "ABC", iter).ToString();
}

Console.WriteLine(sarray[Indent] +"blah");  //now pretend to output some indented line

Мы все любим умное решение, но иногда просто лучше.

Ответ 11

Удивленный никто не пошел в старую школу. Я не претендую на этот код, но просто для удовольствия:

public static string Repeat(this string @this, int count)
{
    var dest = new char[@this.Length * count];
    for (int i = 0; i < dest.Length; i += 1)
    {
        dest[i] = @this[i % @this.Length];
    }
    return new string(dest);
}

Ответ 12

Не уверен, как это будет выполняться, но это простой кусок кода. (Я, вероятно, сделал его более сложным, чем он есть.)

int indentCount = 3;
string indent = "---";
string stringToBeIndented = "Blah";
// Need dummy char NOT in stringToBeIndented - vertical tab, anyone?
char dummy = '\v';
stringToBeIndented.PadLeft(stringToBeIndented.Length + indentCount, dummy).Replace(dummy.ToString(), indent);

В качестве альтернативы, если вы знаете максимальное количество уровней, которые вы можете ожидать, вы можете просто объявить в нем массив и индекс. Вероятно, вы захотите сделать этот массив статическим или постоянным.

string[] indents = new string[4] { "", indent, indent.Replace("-", "--"), indent.Replace("-", "---"), indent.Replace("-", "----") };
output = indents[indentCount] + stringToBeIndented;      

Ответ 13

У меня недостаточно комментариев, чтобы комментировать ответ Адама, но лучший способ сделать это imo:

public static string RepeatString(string content, int numTimes) {
        if(!string.IsNullOrEmpty(content) && numTimes > 0) {
            StringBuilder builder = new StringBuilder(content.Length * numTimes);

            for(int i = 0; i < numTimes; i++) builder.Append(content);

            return builder.ToString();
        }

        return string.Empty;
    }

Вы должны проверить, больше ли numTimes, чем ноль, иначе вы получите исключение.

Ответ 14

Другой подход - рассмотреть string как IEnumerable<char> и иметь общий метод расширения, который будет умножать элементы в коллекции на указанный множитель.

public static IEnumerable<T> Repeat<T>(this IEnumerable<T> source, int times)
{
    source = source.ToArray();
    return Enumerable.Range(0, times).SelectMany(_ => source);
}

Итак, в вашем случае:

string indent = "---";
var f = string.Concat(indent.Repeat(0)); //.NET 4 required
//or
var g = new string(indent.Repeat(5).ToArray());

Ответ 15

Я не видел этого решения. Я нахожу это более простым, когда я в настоящее время занимаюсь разработкой программного обеспечения:

public static void PrintFigure(int shapeSize)
{
    string figure = "\\/";
    for (int loopTwo = 1; loopTwo <= shapeSize - 1; loopTwo++)
    {
        Console.Write($"{figure}");
    }
}

Ответ 16

Распечатать строку с повторением.

Console.Write(new string('=', 30) + "\n");

==============================

Ответ 17

Для общего использования решения, включающие класс StringBuilder, лучше всего подходят для повторения многосимвольных строк. Он оптимизирован для обработки комбинации большого количества строк так, как это не может сделать простая конкатенация, и что было бы трудно или невозможно сделать более эффективно вручную. Решения StringBuilder, показанные здесь, используют O (N) итераций для завершения, фиксированная скорость, пропорциональная количеству повторений.

Тем не менее, для очень большого числа повторов, или когда из него нужно выжать высокий уровень эффективности, лучшим подходом будет сделать нечто похожее на базовую функциональность StringBuilder, но производить дополнительные копии из места назначения, а не из исходной строки, как ниже.

    public static string Repeat_CharArray_LogN(this string str, int times)
    {
        int limit = (int)Math.Log(times, 2);
        char[] buffer = new char[str.Length * times];
        int width = str.Length;
        Array.Copy(str.ToCharArray(), buffer, width);

        for (int index = 0; index < limit; index++)
        {
            Array.Copy(buffer, 0, buffer, width, width);
            width *= 2;
        }
        Array.Copy(buffer, 0, buffer, width, str.Length * times - width);

        return new string(buffer);
    }

Это удваивает длину строки источника/назначения с каждой итерацией, что экономит накладные расходы на сброс счетчиков при каждом прохождении исходной строки, вместо этого плавно читая и копируя теперь гораздо более длинную строку, что современные процессоры могут сделать очень много более эффективно.

Он использует логарифм base-2, чтобы найти, сколько раз ему нужно удвоить длину строки, а затем продолжает делать это столько раз. Поскольку остаток, подлежащий копированию, теперь меньше общей длины, из которой он копируется, он может просто скопировать подмножество того, что уже сгенерировано.

Я использовал метод Array.Copy() вместо использования StringBuilder, так как копирование содержимого StringBuilder в себя будет связано с производством новой строки с этим содержимым с каждой итерацией. Array.Copy() избегает этого, все еще работая с чрезвычайно высокой эффективностью.

Это решение требует O (1 + log N) итераций для завершения, скорость, которая логарифмически увеличивается с числом повторов (удвоение числа повторов равно одной дополнительной итерации), что существенно экономит по сравнению с другими методами, которые увеличиваются пропорционально.

Ответ 18

Вы можете создать ExtensionMethod для этого!

public static class StringExtension
{
  public static string Repeat(this string str, int count)
  {
    string ret = "";

    for (var x = 0; x < count; x++)
    {
      ret += str;
    }

    return ret;
  }
}

Или используя решение @Dan Tao:

public static class StringExtension
{
  public static string Repeat(this string str, int count)
  {
    if (count == 0)
      return "";

    return string.Concat(Enumerable.Repeat(indent, N))
  }
}