Заменить несколько символов в строке C # - PullRequest
155 голосов
/ 01 сентября 2011

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

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

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

Ответы [ 10 ]

187 голосов
/ 01 сентября 2011

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

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

На английском это звучит так:

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

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

Regex pattern = new Regex("[;,\t\r ]|[\n]{2}");
pattern.Replace(myString, "\n");
103 голосов
/ 01 сентября 2011

Если вы чувствуете себя особенно умным и не хотите использовать 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");
52 голосов
/ 01 сентября 2011

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

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');
18 голосов
/ 05 августа 2012

Это кратчайший путь:

myString = Regex.Replace(myString, @"[;,\t\r ]|[\n]{2}", "\n");
7 голосов
/ 09 июня 2015

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

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();
    }
}
5 голосов
/ 12 августа 2017

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

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

  • либо с помощью 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();
2 голосов
/ 17 мая 2018

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

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

1 голос
/ 01 сентября 2011

Используйте 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

0 голосов
/ 24 августа 2018
string ToBeReplaceCharacters = @"~()@#$%&amp;+,'&quot;&lt;&gt;|;\/*?";
string fileName = "filename;with<bad:separators?";

foreach (var RepChar in ToBeReplaceCharacters)
{
    fileName = fileName.Replace(RepChar.ToString(), "");
}
0 голосов
/ 18 мая 2017

Производительность - возможно, это не лучшее решение, но оно работает.

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