如何将正则表达式应用于字符串列表?

时间:2015-07-29 15:26:06

标签: c# regex func

我想知道是否有办法避免以下代码中的foreach循环:

List<string> lines1 = new List<string>();
List<string> lines2 = new List<string>();
lines1.AddRange(File.ReadAllLines("in.txt"));
foreach(string s in lines1)
    lines2.Add(Regex.Replace(s,"bim(.*)","bom$1");

请注意,循环还需要在处理期间有两个列表。我的目标是将一个正则表达式应用于列表 in situ 中的每个字符串。

3 个答案:

答案 0 :(得分:6)

say你不想迭代。然后不要创建一个开头的集合,而是用一个字符串读取整个文件:

string input = File.ReadAllText("in.txt");
string output = Regex.Replace(input, "bim(.*)", "bom$1");

然后,如果您想获得输入中的“行”,请按照Easiest way to split a string on newlines in .NET?中的说明拆分输出:

string[] outputLines = input.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);

答案 1 :(得分:4)

您无法使用foreach执行此操作,因为在迭代时无法修改集合,但您可以使用for

List<string> lines = new List<string>(File.ReadAllLines("in.txt"));
for(int i = 0; i < lines.Count; i++)
    lines[i] = Regex.Replace(lines[i],"bim(.*)","bom$1");

或者单行:

List<string> lines = File.ReadLines("in.txt")
                         .Select(s => Regex.Replace(s ,"bim(.*)","bom$1"))
                         .ToList();

请注意,ReadLines不会将整个文件读入内存,因此投影将在从文件中读取时转换行(意味着不会创建第二个集合)。

答案 2 :(得分:3)

只需使用常规for循环即可避免需要额外的列表

for (var i=0; i<lines1.Count; i++)
{
    lines1[i] = Regex.Replace(lines1[i],"bim(.*)","bom$1");
}

但请注意, 仍在为lines1中的每个字符串创建一个新字符串,因为字符串是不可变的。

或者,如果你愿意,你可以写一个扩展方法,这样的东西应该可以工作:

public static class Extensions
{
    public static IEnumerable<string> RegexReplace (this IEnumerable<string> strings, Regex regex, string replacement)
    {
        foreach (var s in strings)
        {
            yield return regex.Replace(s, replacement);
        }
    }
}

你可以这样称呼它:

var lines1 = File.ReadLines("in.txt").RegexReplace("bim(.*)","bom$1");

此扩展允许您将正则表达式应用于集合中的每个字符串,并且因为它使用延迟执行,所以在迭代之前它实际上不会执行任何操作。因此,例如,如果您只需要检查第一行(可能决定是否应该处理文件的其余部分),您就可以在不查看其余行的情况下快捷方式。在这种情况下,我们可以O(1)获得最佳案例。