从列表中删除重复的捕获
Remove Duplicate Captures from List
我是 .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 个数字。
因此,例如,它应该在以下文本块中捕获 "C61, C62, C61"-
blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345
Main Storage : C61
C62 : 1215
C61 : 1785
blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345
到目前为止一切顺利。我的问题是 - 我如何才能让它只捕获一次特定的匹配项?所以在上面的例子中,我希望它最终吐出 "C61, C62" 而不是 "C61, C62, C61"。这对 RegEx 是否可行,或者我应该在 RegEx 完成捕获后操作列表?无论哪种方式,我将如何处理它?
在此先感谢您提供的任何帮助。
尝试使用
list.Distinct().ToList();
@Nefarrii 回答了如何从列表中删除重复项,这绝对是这里应该做的!它更快、更容易、更便宜、更好。
如果你想知道,我会为正则表达式部分做出贡献 - 是的,它可以完成。
您已经捕获了每个令牌,所以您需要做的就是使用 lookahead to check if "it's not followed by the same text" (using a 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 );
}
我是 .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 个数字。
因此,例如,它应该在以下文本块中捕获 "C61, C62, C61"-
blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345
Main Storage : C61
C62 : 1215
C61 : 1785blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345blablablabla12345
到目前为止一切顺利。我的问题是 - 我如何才能让它只捕获一次特定的匹配项?所以在上面的例子中,我希望它最终吐出 "C61, C62" 而不是 "C61, C62, C61"。这对 RegEx 是否可行,或者我应该在 RegEx 完成捕获后操作列表?无论哪种方式,我将如何处理它?
在此先感谢您提供的任何帮助。
尝试使用
list.Distinct().ToList();
@Nefarrii 回答了如何从列表中删除重复项,这绝对是这里应该做的!它更快、更容易、更便宜、更好。
如果你想知道,我会为正则表达式部分做出贡献 - 是的,它可以完成。
您已经捕获了每个令牌,所以您需要做的就是使用 lookahead to check if "it's not followed by the same text" (using a 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 );
}