Заменить несколько символов в строке С#

Есть ли лучший способ заменить строки?

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

myString.Replace(';', '\n').Replace(',', '\n').Replace('\r', '\n').Replace('\t', '\n').Replace(' ', '\n').Replace("\n\n", "\n");

Ответ 1

Вы можете использовать регулярное выражение replace.

s/[;,\t\r ]|[\n]{2}/\n/g
  • s/ в начале означает поиск
  • Символы между [ и ] являются символами для поиска (в любом порядке)
  • Второй / ограничивает текст для поиска и текст замены

На английском языке это гласит:

"Найдите ; или , или \t или \r или (пробел) или ровно два последовательных \n и замените их на \n"

В С# вы можете сделать следующее: (после импорта System.Text.RegularExpressions)

Regex pattern = new Regex("[;,\t\r ]|[\n]{2}");
pattern.Replace(myString, "\n");

Ответ 2

Если вы чувствуете себя особенно умным и не хотите использовать Regex:

char[] separators = new char[]{' ',';',',','\r','\t','\n'};

string s = "this;is,\ra\t\n\n\ntest";
string[] temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
s = String.Join("\n", temp);

Вы можете обернуть это в метод расширения с небольшими усилиями.

Изменить: или просто подождите 2 минуты, и я все равно напишу его:)

public static class ExtensionMethods
{
   public static string Replace(this string s, char[] separators, string newVal)
   {
       string[] temp;

       temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
       return String.Join( newVal, temp );
   }
}

И вуаля...

char[] separators = new char[]{' ',';',',','\r','\t','\n'};
string s = "this;is,\ra\t\n\n\ntest";

s = s.Replace(separators, "\n");

Ответ 3

Вы можете использовать функцию Linq Aggregate:

string s = "the\nquick\tbrown\rdog,jumped;over the lazy fox.";
char[] chars = new char[] { ' ', ';', ',', '\r', '\t', '\n' };
string snew = chars.Aggregate(s, (c1, c2) => c1.Replace(c2, '\n'));

Вот метод расширения:

public static string ReplaceAll(this string seed, char[] chars, char replacementCharacter)
{
    return chars.Aggregate(seed, (str, cItem) => str.Replace(cItem, replacementCharacter));
}

Пример использования метода расширения:

string snew = s.ReplaceAll(chars, '\n');

Ответ 4

Это самый короткий путь:

myString = Regex.Replace(myString, @"[;,\t\r ]|[\n]{2}", "\n");

Ответ 5

Ой, ужас производительности! Ответ немного устарел, но все же...

public static class StringUtils
{
    #region Private members

    [ThreadStatic]
    private static StringBuilder m_ReplaceSB;

    private static StringBuilder GetReplaceSB(int capacity)
    {
        var result = m_ReplaceSB;

        if (null == result)
        {
            result = new StringBuilder(capacity);
            m_ReplaceSB = result;
        }
        else
        {
            result.Clear();
            result.EnsureCapacity(capacity);
        }

        return result;
    }


    public static string ReplaceAny(this string s, char replaceWith, params char[] chars)
    {
        if (null == chars)
            return s;

        if (null == s)
            return null;

        StringBuilder sb = null;

        for (int i = 0, count = s.Length; i < count; i++)
        {
            var temp = s[i];
            var replace = false;

            for (int j = 0, cc = chars.Length; j < cc; j++)
                if (temp == chars[j])
                {
                    if (null == sb)
                    {
                        sb = GetReplaceSB(count);
                        if (i > 0)
                            sb.Append(s, 0, i);
                    }

                    replace = true;
                    break;
                }

            if (replace)
                sb.Append(replaceWith);
            else
                if (null != sb)
                    sb.Append(temp);
        }

        return null == sb ? s : sb.ToString();
    }
}

Ответ 6

Строки - это просто неизменяемые массивы символов

Вам просто нужно сделать его изменчивым:

  • либо с помощью StringBuilder
  • идти в unsafe мир и играть с указателями (хотя опасно)

и попробуйте перебрать массив символов наименьшее количество раз. Обратите внимание на HashSet здесь, так как он избегает обхода последовательности символов внутри цикла. Если вам нужен еще более быстрый поиск, вы можете заменить HashSet оптимизированным поиском char (на основе array[256]).

Пример с StringBuilder

public static void MultiReplace(this StringBuilder builder, 
    char[] toReplace, 
    char replacement)
{
    HashSet<char> set = new HashSet<char>(toReplace);
    for (int i = 0; i < builder.Length; ++i)
    {
        var currentCharacter = builder[i];
        if (set.Contains(currentCharacter))
        {
            builder[i] = replacement;
        }
    }
}

Редактировать - Оптимизированная версия

public static void MultiReplace(this StringBuilder builder, 
    char[] toReplace,
    char replacement)
{
    var set = new bool[256];
    foreach (var charToReplace in toReplace)
    {
        set[charToReplace] = true;
    }
    for (int i = 0; i < builder.Length; ++i)
    {
        var currentCharacter = builder[i];
        if (set[currentCharacter])
        {
            builder[i] = replacement;
        }
    }
}

Тогда вы просто используете это так:

var builder = new StringBuilder("my bad,url&slugs");
builder.MultiReplace(new []{' ', '&', ','}, '-');
var result = builder.ToString();

Ответ 7

Вы также можете просто написать эти методы расширения строк и поместить их в свое решение:

using System.Text;

public static class StringExtensions
{
    public static string ReplaceAll(this string original, string toBeReplaced, string newValue)
    {
        if (string.IsNullOrEmpty(original) || string.IsNullOrEmpty(toBeReplaced)) return original;
        if (newValue == null) newValue = string.Empty;
        StringBuilder sb = new StringBuilder();
        foreach (char ch in original)
        {
            if (toBeReplaced.IndexOf(ch) < 0) sb.Append(ch);
            else sb.Append(newValue);
        }
        return sb.ToString();
    }

    public static string ReplaceAll(this string original, string[] toBeReplaced, string newValue)
    {
        if (string.IsNullOrEmpty(original) || toBeReplaced == null || toBeReplaced.Length <= 0) return original;
        if (newValue == null) newValue = string.Empty;
        foreach (string str in toBeReplaced)
            if (!string.IsNullOrEmpty(str))
                original = original.Replace(str, newValue);
        return original;
    }
}


Назовите их так:

"ABCDE".ReplaceAll("ACE", "xy");

xyBxyDxy


И это:

"ABCDEF".ReplaceAll(new string[] { "AB", "DE", "EF" }, "xy");

xyCxyF

Ответ 8

Используйте RegEx.Replace, что-то вроде этого:

  string input = "This is   text with   far  too   much   " + 
                 "whitespace.";
  string pattern = "[;,]";
  string replacement = "\n";
  Regex rgx = new Regex(pattern);

Подробнее об этом Документация MSDN для RegEx.Replace

Ответ 9

Performance-Wise, возможно, это не лучшее решение, но оно работает.

var str = "filename:with&bad$separators.txt";
char[] charArray = new char[] { '#', '%', '&', '{', '}', '\\', '<', '>', '*', '?', '/', ' ', '$', '!', '\'', '"', ':', '@' };
foreach (var singleChar in charArray)
{
   str = str.Replace(singleChar, '_');
}

Ответ 10

string ToBeReplaceCharacters = @"~()@#$%&amp;+,'&quot;&lt;&gt;|;\/*?";
string fileName = "filename;with<bad:separators?";

foreach (var RepChar in ToBeReplaceCharacters)
{
    fileName = fileName.Replace(RepChar.ToString(), "");
}