Замените список недопустимых символов их действительной версией (например, tr) - PullRequest
6 голосов
/ 30 мая 2011

Мне нужно сделать что-то вроде этого: .trReplace:

  str = str.trReplace("áéíüñ","aeiu&");

Это должно изменить эту строку:

  a stríng with inválid charactérs

на:

  a string with invalid characters

Мои текущие идеи:

 str = str.Replace("á","a").Replace("é","e").Replace("í","ï"...

и:

 sb = new StringBuilder(str)
 sb.Replace("á","a").
 sb.Replace("é","e")
 sb.Replace("í","ï"...

Но я не думаю, что они эффективны для длинных строк.

Ответы [ 3 ]

4 голосов
/ 30 мая 2011

У Ричарда хороший ответ, но производительность на более длинных струнах может немного снизиться (примерно на 25% медленнее, чем при замене прямой строки, как показано в вопросе). Я чувствовал себя законченным, чтобы посмотреть на это немного дальше. На самом деле, в StackOverflow уже есть несколько хороших связанных ответов:

Самый быстрый способ удалить символы из строки

C # Разбор / преобразование одного или нескольких символов

Существует также хорошая статья о CodeProject, охватывающая различные варианты.

http://www.codeproject.com/KB/string/fastestcscaseinsstringrep.aspx

Объяснить, почему функция, представленная в ответе Ричардса, становится медленнее с более длинными строками, связано с тем, что замены происходят по одному символу за раз; таким образом, если у вас есть большие последовательности не сопоставленных символов, вы тратите лишние циклы, повторно добавляя вместе строку. Таким образом, если вы хотите взять несколько моментов из статьи CodePlex, вы получите слегка измененную версию ответа Ричардса, которая выглядит следующим образом:

private static readonly Char[] ReplacementChars = new[] { 'á', 'é', 'í', 'ü', 'ñ' };
private static readonly Dictionary<Char, Char> ReplacementMappings = new Dictionary<Char, Char>
                                                               {
                                                                 { 'á', 'a'},
                                                                 { 'é', 'e'},
                                                                 { 'í', 'i'},
                                                                 { 'ü', 'u'},
                                                                 { 'ñ', '&'}
                                                               };

private static string Translate(String source)
{
  var startIndex = 0;
  var currentIndex = 0;
  var result = new StringBuilder(source.Length);

  while ((currentIndex = source.IndexOfAny(ReplacementChars, startIndex)) != -1)
  {
    result.Append(source.Substring(startIndex, currentIndex - startIndex));
    result.Append(ReplacementMappings[source[currentIndex]]);

    startIndex = currentIndex + 1;
  }

  if (startIndex == 0)
    return source;

  result.Append(source.Substring(startIndex));

  return result.ToString();
}

ПРИМЕЧАНИЕ Не все граничные случаи были проверены.

ПРИМЕЧАНИЕ Может заменить ReplacementChars на ReplacementMappings.Keys.ToArray () за небольшую плату.

Предполагая, что НЕ каждый символ является заменяющим символом, тогда он будет работать немного быстрее, чем прямые замены строк (опять же около 20%).

При этом помните, что при рассмотрении затрат на производительность, о чем мы на самом деле говорим ... в данном случае ... разница между оптимизированным решением и исходным решением составляет около 1 секунды на 100 000 итераций на строке из 1000 символов.

В любом случае, просто хотел добавить информацию к ответам на этот вопрос.

2 голосов
/ 30 мая 2011

Я сделал нечто подобное для паспортов ИКАО.Имена должны были быть «транслитерированы».В основном у меня был словарь сопоставления символов с символами.

Dictionary<char, char> mappings;

static public string Translate(string s)
{
   var t = new StringBuilder(s.Length);
   foreach (char c in s)
   {
      char to;
      if (mappings.TryGetValue(c, out to))
         t.Append(to);
      else
         t.Append(c);
    }
    return t.ToString();
 }
1 голос
/ 30 мая 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...