c# - 从列表中删除重复的捕获

标签 c# regex .net-4.6

我是 .NET 新手,对 RegEx 不太熟悉,但我有以下代码 -

    var p = GetAllMatches(lines, @"^\s+?([A-Z]{1,2}[0-9]{2}) : |: ([A-Z]{1,2}[0-9]{2})")
                        .SelectMany(m => m.Groups[1].Captures.Cast<Capture>().Select(c => c.Value).ToList())
                        .ToList();


    private static List<Match> GetAllMatches(List<string> lines, string pattern, RegexOptions options=RegexOptions.None)
    {
        return lines
            .Select(l => Regex.Match(l, pattern, options))
            .Where(m => m.Success)
            .ToList(); 
    }

...我认为,它捕获以“:”开头并后跟 1 或 2 个字母字符和 2 个数字的字符串部分,或者以“:”结尾且前面的字符串部分由 1 或 2 个字母字符和 2 个数字组成。

因此,例如,它应该捕获以下文本 block 中的“C61,C62,C61”-

blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345

Main Storage : C61
C62 : 1215
C61 : 1785

blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345

到目前为止一切顺利。我的问题是这样的 - 我该如何制作它,以便它只捕获一次特定的匹配?所以在上面的例子中,我希望它最终吐出“C61,C62”而不是“C61,C62,C61”。这对于 RegEx 来说是可能的吗?还是我应该在 RegEx 完成捕获后操作该列表?无论哪种方式,我将如何处理它?<​​/p>

预先感谢您提供的任何帮助。

最佳答案

@Nefarrii 回答了如何从列表中删除重复项,这绝对是这里应该做的!它更快、更容易、更便宜、更好。

如果您想知道,我将为正则表达式部分做出贡献 - 是的,可以做到。

您已经捕获了每个 token ,因此您需要做的就是使用 lookahead检查是否“后面没有相同的文本”(使用 backreference )。

正则表达式:

(?: : (?<portion>[A-Z]{1,2}[0-9]{2})|^\s*(?<portion>[A-Z]{1,2}[0-9]{2}) :)(?!.*(?: : \k<portion>|^\s*\k<portion> :))
       ^^^^^^^^^^                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 (same group, with a name)           (negative lookahead: it's not followed by the text captured in group <portion>)
  • 使用RegexOptions.Singleline | RegexOptions.Multiline
  • 请注意,我正在使用 named groups .


代码:

string input = "blablablabla12345b\nMain Storage : C61\nC62 : 1215\nC61 : 1785\nblablablabla12345blablablabla";

string pattern = @"(?: : (?<portion>[A-Z]{1,2}[0-9]{2})|^\s*(?<portion>[A-Z]{1,2}[0-9]{2}) :)(?!.*(?: : \k<portion>|^\s*\k<portion> :))";
MatchCollection matches = Regex.Matches(input, pattern, RegexOptions.Singleline | RegexOptions.Multiline);

foreach (Match match in matches)
{
     GroupCollection groups = match.Groups;
     Console.WriteLine( groups["portion"].Value );
}

ideone Demo

关于c# - 从列表中删除重复的捕获,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32896855/

相关文章:

.net 4.6 中的 Websocket 连接失败

c# - 解释ds.Tables[0].Rows.Count?

c# - 如何在 C# 系统托盘应用程序中重复运行代码(如定时器)?

javascript - 从两个不同的字符串中选择

ios - 检查 NSString 中的平衡括号时忽略表情符号

javascript - 这个正则表达式是什么意思?

azure - ASP.NET 5 Web 应用程序作为 Azure Web 角色?

c# - 字符串编码错误(Windows 10 + Visual Studio 2015 + Net 4.6)

c# - 为什么此参数不符合 CLS?

c# - 在类中展平数组的动态方法?