Символы редактирования в Строке в C#

Каков самый чистый способ отредактировать символы в строке в C#?

Что является эквивалентом C# этого в C++:

std::string myString = "boom";
myString[0] = "d";
13
задан George Stocker 9 June 2010 в 18:50
поделиться

11 ответов

Решил отследить то, что я почувствовал, где два наиболее канонических подхода, плюс один, который я добавил как непредставленный; вот что я обнаружил (сборка релиза):

ReplaceAtChars: 86ms
ReplaceAtSubstring: 258ms
ReplaceAtStringBuilder: 161ms

Очевидно, что подход массива Char лучше всего оптимизирован средой выполнения. Это фактически говорит о том, что текущий ведущий ответ (StringBuilder), вероятно, не является лучшим ответом.

И вот тест, который я использовал:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("ReplaceAtChars: " + new Stopwatch().Time(() => "test".ReplaceAtChars(1, 'E').ReplaceAtChars(3, 'T'), 1000000) + "ms");
        Console.WriteLine("ReplaceAtSubstring: " + new Stopwatch().Time(() => "test".ReplaceAtSubstring(1, 'E').ReplaceAtSubstring(3, 'T'), 1000000) + "ms");
        Console.WriteLine("ReplaceAtStringBuilder: " + new Stopwatch().Time(() => "test".ReplaceAtStringBuilder(1, 'E').ReplaceAtStringBuilder(3, 'T'), 1000000) + "ms");
    }
}

public static class ReplaceAtExtensions
{
    public static string ReplaceAtChars(this string source, int index, char replacement)
    {
        var temp = source.ToCharArray();
        temp[index] = replacement;
        return new String(temp);
    }

    public static string ReplaceAtStringBuilder(this string source, int index, char replacement)
    {
        var sb = new StringBuilder(source);
        sb[index] = replacement;
        return sb.ToString();
    }

    public static string ReplaceAtSubstring(this string source, int index, char replacement)
    {
        return source.Substring(0, index) + replacement + source.Substring(index + 1);
    }
}

public static class StopwatchExtensions
{
    public static long Time(this Stopwatch sw, Action action, int iterations)
    {
        sw.Reset();
        sw.Start();
        for (int i = 0; i < iterations; i++)
        {
            action();
        }
        sw.Stop();

        return sw.ElapsedMilliseconds;
    }
}
15
ответ дан 1 December 2019 в 17:12
поделиться

Строки в .Net являются неизменяемыми. Это означает, что вы не можете редактировать их. Все, что вы можете сделать, это создать новые. Вы должны сделать что-то вроде этого:

string myString = "boom";
myString = "d" + myString.Substring(1);
8
ответ дан 1 December 2019 в 17:12
поделиться

Попробуйте использовать string.replace

http://msdn.microsoft.com/en-us/library/fk49wtc1.aspx

Возможно, это самый чистый и простой способ.

1
ответ дан 1 December 2019 в 17:12
поделиться

Вместо этого используйте StringBuilder.

строка неизменяема, как описано в MSDN:

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

Поэтому вы хотите получить что-то вроде:

 StringBuilder sb = new StringBuilder("Bello World!");
 sb[0] = 'H';
 string str = sb.ToString();
30
ответ дан 1 December 2019 в 17:12
поделиться

Строки неизменяемы, поэтому вы не можете просто изменить их.

Вы можете получить char[] из строки, внести свои изменения и создать новую строку из измененного массива.

Вы можете использовать такие вещи, как replace, хотя они не дают вам контроля над каждым символом, как это делает C. Они также будут создавать новую строку при каждом изменении, в то время как стиль char[] позволяет вносить все изменения и затем создавать из них новую строку.

8
ответ дан 1 December 2019 в 17:12
поделиться
string myString = "boom";
char[] arr = myString.ToCharArray();
arr[0] = 'd';
myString = new String(arr);
3
ответ дан 1 December 2019 в 17:12
поделиться

Вы не можете, поскольку строки неизменяемы.

Вы всегда можете использовать собственный метод расширения, чтобы сделать что-то подобное:

public static string ReplaceAtIndex(this string original, 
    int index, char character)
{
    char[] temp = original.ToCharArray();
    temp[index] = character;
    return new String(temp);
}

И называть его так:

string newString = myString.ReplaceAtIndex(0, 'd');
5
ответ дан 1 December 2019 в 17:12
поделиться
string myString = "boom";
char[] myChars = myString.ToCharArray();
myChars[0] = 'd';
myString = new String(myChars);
3
ответ дан 1 December 2019 в 17:12
поделиться

Как сказал Брайан, используйте StringBuilder, вместо этого:

string myString = "boom";
StringBuilder myStringBuilder = new StringBuilder(myString);
myStringBuilder[0] = 'd';
// Whatever else you're going to do to it

Когда вам снова понадобится строка, вызовите myStringBuilder.ToString()

4
ответ дан 1 December 2019 в 17:12
поделиться

Вот забавный, который я собрал. Учтите, что это не очень эффективно, особенно при простой замене. Тем не менее, писать это было весело, и он дает довольно читаемый шаблон использования. Это также подчеркивает малоизвестный факт, что String реализует IEnumerable.

public static class LinqToStrings
{
    public static IQueryable<char> LinqReplace(this string source, int startIndex, int length, string replacement)
    {
        var querySource = source.AsQueryable();
        return querySource.LinqReplace(startIndex, length, replacement);
    }

    public static IQueryable<char> LinqReplace(this IQueryable<char> source, int startIndex, int length, string replacement)
    {
        var querySource = source.AsQueryable();
        return querySource.Take(startIndex).Concat(replacement).Concat(querySource.Skip(startIndex + length));
    }

    public static string AsString(this IQueryable<char> source)
    {
        return new string(source.ToArray());
    }
}

И вот несколько примеров использования:

public void test()
{
    var test = "test";
    Console.WriteLine("Old: " + test);
    Console.WriteLine("New: " + test.LinqReplace(0, 4, "SOMEPIG")
                                    .LinqReplace(4, 0, "terrific")
                                    .AsString());
}

Выводы:

Old: test
New: SOMEterrificPIG

Другая версия того же подхода, которая не так уж ужасно медленна, проста с использованием Substring:

public static string ReplaceAt(this string source, int startIndex, int length, string replacement)
{
    return source.Substring(0, startIndex) + replacement + source.Substring(startIndex + length);
}

И в замечательном примере того, почему вы должны профилировать свой код , и почему вам, вероятно, не следует не использовать мою реализацию LinqToStrings в производственном коде, вот временный тест:

Console.WriteLine("Using LinqToStrings: " + new Stopwatch().Time(() => "test".LinqReplace(0, 4, "SOMEPIG").LinqReplace(4, 0, "terrific").AsString(), 1000));
Console.WriteLine("Using Substrings: " + new Stopwatch().Time(() => "test".ReplaceAt(0, 4, "SOMEPIG").ReplaceAt(4, 0, "terrific"), 1000));

который измеряет такты таймера за 1000 итераций и дает следующий результат:

Using LinqToStrings: 3,818,953
Using Substrings: 1,157
2
ответ дан 1 December 2019 в 17:12
поделиться

Строки неизменяемы в C#. Используйте класс StringBuilder или символьный массив.

StringBuilder sb = new StringBuilder("boom");
sb[0] = 'd';

IIRC, в .NET используется так называемый пул строк. Каждый раз, когда создается новый строковый литерал, он сохраняется в памяти как часть пула строк. Если вы создадите вторую строку, которая совпадает со строкой в пуле строк, обе переменные будут ссылаться на одну и ту же память.

Когда вы пытаетесь выполнить такую операцию, как замена символа 'b' на символ 'd' с помощью строк в .NET, ваша программа фактически создает вторую строку в пуле строк со значением "doom", хотя с вашей точки зрения кажется, что этого не происходит. Читая код, можно предположить, что происходит замена символа.

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

2
ответ дан 1 December 2019 в 17:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: