замена строки с использованием List <string> - PullRequest
13 голосов
/ 14 сентября 2010

У меня есть список слов, которые я хочу игнорировать, например:

public List<String> ignoreList = new List<String>()
        {
            "North",
            "South",
            "East",
            "West"
        };

Для данной строки, скажем, "14th Avenue North" Я хочу иметь возможность удалить "северную" часть, поэтому в основном функция, которая при вызове возвращает "14th Avenue ".

Я чувствую, что могу кое-что сделать со смесью LINQ, regex и replace, но я просто не могу этого понять.

В целом, я пытаюсь написать алгоритм сопоставления адресов. Я хочу отфильтровать такие слова, как «Улица», «Север», «Бульвар» и т. Д., Прежде чем использовать алгоритм Левенштейна для оценки сходства.

Ответы [ 11 ]

12 голосов
/ 14 сентября 2010

Как насчет этого:

string.Join(" ", text.Split().Where(w => !ignoreList.Contains(w)));

или для .Net 3:

string.Join(" ", text.Split().Where(w => !ignoreList.Contains(w)).ToArray());

Обратите внимание, что этот метод разбивает строку на отдельные слова, поэтому он удаляет только целые слова. Таким образом, он будет правильно работать с адресами, такими как Northampton Way #123, с которыми string.Replace не справится.

6 голосов
/ 14 сентября 2010
Regex r = new Regex(string.Join("|", ignoreList.Select(s => Regex.Escape(s)).ToArray()));
string s = "14th Avenue North";
s = r.Replace(s, string.Empty);
2 голосов
/ 14 сентября 2010

Если вы знаете, что список слов содержит только символы, которые не нужно экранировать внутри регулярного выражения, вы можете сделать это:

string s = "14th Avenue North";
Regex regex = new Regex(string.Format(@"\b({0})\b",
                        string.Join("|", ignoreList.ToArray())));
s = regex.Replace(s, "");

Результат:

14th Avenue 

ЕслиСуществуют специальные символы, которые вам необходимо исправить:

  • Используйте Regex.Escape для каждого элемента списка игнорирования.
  • Граница слова \b не будет совпадать с пробеломс последующим символом или наоборот.Возможно, вам придется проверить наличие пробелов (или других разделяющих символов, таких как знаки пунктуации), используя вместо этого косвенные утверждения.

Вот как исправить эти две проблемы:

Regex regex = new Regex(string.Format(@"(?<= |^)({0})(?= |$)",
    string.Join("|", ignoreList.Select(x => Regex.Escape(x)).ToArray())));
2 голосов
/ 14 сентября 2010

Что не так с простым циклом for?

string street = "14th Avenue North";
foreach (string word in ignoreList)
{
    street = street.Replace(word, string.Empty);
}
2 голосов
/ 14 сентября 2010

Примерно так должно работать:

string FilterAllValuesFromIgnoreList(string someStringToFilter)
{
  return ignoreList.Aggregate(someStringToFilter, (str, filter)=>str.Replace(filter, ""));
}
1 голос
/ 15 сентября 2010

LINQ делает это легко и читабельно. Это требует нормализованных данных, особенно в том, что они чувствительны к регистру.

List<string> ignoreList = new List<string>()
{
    "North",
    "South",
    "East",
    "West"
};    

string s = "123 West 5th St"
        .Split(' ')  // Separate the words to an array
        .ToList()    // Convert array to TList<>
        .Except(ignoreList) // Remove ignored keywords
        .Aggregate((s1, s2) => s1 + " " + s2); // Reconstruct the string
1 голос
/ 14 сентября 2010

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

address = ignoreList.Aggregate(address, (a, s) => a.Replace(s, String.Empty));

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

0 голосов
/ 14 сентября 2010

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

string s = "14th Avenue North"
ignoreList.ForEach(i => s = s.Replace(i, ""));
//result is "14th Avenue "
0 голосов
/ 14 сентября 2010

Почему бы не сделать это просто?

public static string Trim(string text)
{
   var rv = text.trim();
   foreach (var ignore in ignoreList) {
      if(tv.EndsWith(ignore) {
      rv = rv.Replace(ignore, string.Empty);
   }
  }
   return rv;
}
0 голосов
/ 14 сентября 2010

Если у вас есть список, я думаю, вам придется коснуться всех предметов.Вы могли бы создать массивный RegEx со всеми вашими ключевыми словами игнорирования и заменить на String.Empty.

Вот начало:

(^|\s+)(North|South|East|West){1,2}(ern)?(\s+|$)

Если у вас есть один RegEx для игнорирования слов, вы можетеодна замена для каждой фразы, которую вы хотите передать алгоритму.

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