C# 使用列表替换字符串<;字符串>;

C# 使用列表替换字符串<;字符串>;,c#,.net,regex,string,replace,C#,.net,Regex,String,Replace,我有一个我想忽略的单词列表,比如: public List<String> ignoreList = new List<String>() { "North", "South", "East", "West" }; public List ignoreList=new List() { “北方”, “南方”, “东方”, “西部” }; 对于

我有一个我想忽略的单词列表,比如:

public List<String> ignoreList = new List<String>()
        {
            "North",
            "South",
            "East",
            "West"
        };
public List ignoreList=new List()
{
“北方”,
“南方”,
“东方”,
“西部”
};
对于给定的字符串,比如说
“14th Avenue North”
我希望能够删除“North”部分,因此基本上是一个调用时返回
“14th Avenue”
的函数

我觉得我应该能够用LINQ、regex和replace的组合来做一些事情,但我就是想不出来


更重要的是,我正在尝试编写一个地址匹配算法。在使用Levenshtein算法评估相似度之前,我想过滤掉“Street”、“North”、“Boulevard”等词。

类似的方法应该可以:

string FilterAllValuesFromIgnoreList(string someStringToFilter)
{
  return ignoreList.Aggregate(someStringToFilter, (str, filter)=>str.Replace(filter, ""));
}
为Gabe更新



简单的for循环有什么问题

string street = "14th Avenue North";
foreach (string word in ignoreList)
{
    street = street.Replace(word, string.Empty);
}

如果你有一个清单,我想你必须触摸所有的项目。您可以创建一个包含所有ignore关键字的大型正则表达式,并替换为
String.Empty

这是一个开始:

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

如果您有一个用于忽略单词的正则表达式,那么您可以对要传递给算法的每个短语进行一次替换。

为什么juts不保持简单

Regex r = new Regex(string.Join("|", ignoreList.Select(s => Regex.Escape(s)).ToArray()));
string s = "14th Avenue North";
s = r.Replace(s, string.Empty);
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;
}

如果它是一个短字符串(如示例中所示),则可以循环遍历这些字符串并一次替换一个。如果您想获得更多乐趣,可以使用LINQ聚合方法:

address = ignoreList.Aggregate(address, (a, s) => a.Replace(s, String.Empty));
如果是一根大的绳子,那会很慢。相反,您可以在一次运行字符串中替换所有字符串,这要快得多。我在中为此制定了一个方法。

这个怎么样:

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
无法处理的地址上正常工作。

如果您知道单词列表只包含不需要在正则表达式中转义的字符,则可以执行以下操作:

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

14th Avenue
如果愿意的话,可以使用and表达式来实现这一点,但要改变它,要比使用聚合更容易。我会这样做:

string s = "14th Avenue North"
ignoreList.ForEach(i => s = s.Replace(i, ""));
//result is "14th Avenue "

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
List ignoreList=新列表()
{
“北方”,
“南方”,
“东方”,
“西部”
};    
字符串s=“123西五街”
.Split(“”)//将单词分隔为一个数组
.ToList()//将数组转换为TList
.Exception(ignoreList)//删除忽略的关键字
.聚合((s1,s2)=>s1+“”+s2);//重建字符串


没有LINQ,没有RegExp,但它是正确的。我唯一要改变的是使用空字符串文字。不,不正确。这将把“123北安普敦”变成“123安普敦”。关闭…现在你需要确保你把单词之间的空格放回原处。我想我们可以。我们真的想吗?这是个好的开始。现在,让它只匹配整个单词。我们使用这种方法,根据查看数据生成的正则表达式关键字,将大量客户标记为商业或住宅。我可能已经将参数交换到第二个lambda,但这肯定会起作用,聚合是一种非常强大的方法,它的跛脚人不经常使用它。应该注意的是,我怀疑多次调用Replace不是最有效的方法。也许将列表的内容构建到静态正则表达式中并使用它来替换会更快一些,但我怀疑在这种情况下,差异并不重要。这是不正确的,因为它使用的是
string.replace
,它不能仅在单词边界上匹配。不过,如果要使用正则表达式,它应该使用单个编译的正则表达式。好的一点@Gabe该示例更多地是关于聚合的使用,而不是替换。如果有特殊字符,则应该转义ignoreList中的内容:string.Join(“|”),ignoreList.select(s=>RegEx.escape(s)).ToArray()由于很有可能列表中会包含类似于
“St.”
,因此建议逃逸。你只需要寻找整句话。@Frank正确。虽然没有具体说明列表的来源。首先编写正确的正则表达式可能比从列表转换正则表达式更容易,除非确实需要列表。是的,只有当列表内容可能发生变化时,动态构建正则表达式才真正有价值。一般来说,使用正则表达式只有在经常使用该函数时才有用,因为它可能比N字符串替换更快。但它不是一行@htw。如果不是一行,你不会得到任何极客分数。不要让这个程序在北卡罗来纳州夏洛特运行。著名的道路名称恰好是东大街、南大街、西大街。这些是道路的名称,而不是你现在在西一街的区别。在这一点上,还有其他情况下,您的方向不是真正的方向,而是标识符的关键部分。北安普敦、北湖(夏洛特的购物中心/地区)、北卡罗莱纳州、北达科他州等等@Anthony:这是真的,我会小心我放在字典里的东西。但是,我首先匹配邮政编码(zip),它必须与函数完全匹配,甚至考虑地址。从那以后,我真的不介意我是否宁愿得到误报而错过结果。然后你会很高兴知道东、西和南BLVD都是相交的!他们将共享一个拉链!我相信如果你能让你的程序在夏洛特运行,你可以让它在任何地方运行。加拿大完全没有北/南街道/大道?我认为Anthony的评论比你的问题陈述更笼统。非常感谢。我的忽略列表显然比我在这里发布的要长得多,但不确定是否足够长,可以使用您的方法。我将对它进行分析,然后再看一看。这是一个非常好的例子
Regex regex = new Regex(string.Format(@"(?<= |^)({0})(?= |$)",
    string.Join("|", ignoreList.Select(x => Regex.Escape(x)).ToArray())));
string s = "14th Avenue North"
ignoreList.ForEach(i => s = s.Replace(i, ""));
//result is "14th Avenue "
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