regex - 通过 linq 中的部分字符串区分

标签 regex linq linq-to-objects

鉴于此集合:

var list = new [] {
    "1.one",
    "2. two",
    "no number",
    "2.duplicate",
    "300. three hundred",
    "4-ignore this"};

如何使用 获取以数字开头的项目子集,后跟一个点( 正则表达式 @"^\d+(?=\.)" )独特 数字?那是:
{"1.one", "2. two", "300. three hundred"}

更新:

我对此的尝试是使用 IEqualityComparer传递给 Distinct方法。我借了这个 GenericCompare类并尝试了以下代码无济于事:
var pattern = @"^\d+(?=\.)";
var comparer = new GenericCompare<string>(s => Regex.Match(s, pattern).Value);
list.Where(f => Regex.IsMatch(f, pattern)).Distinct(comparer);

最佳答案

如果您喜欢使用 Linq 的方法,您可以尝试向正则表达式添加一个命名的捕获组,然后过滤与正则表达式匹配的项目,按捕获的数字分组,最后只获取每个数字的第一个字符串。我喜欢解决方案的可读性,但如果有更有效的方法来消除重复,我不会感到惊讶,让我们看看其他人是否提出了不同的方法。

像这样的东西:

list.Where(s => regex.IsMatch(s))
    .GroupBy(s => regex.Match(s).Groups["num"].Value)
    .Select(g => g.First())

您可以尝试使用此示例:
public class Program
{
    private static readonly Regex regex = new Regex(@"^(?<num>\d+)\.", RegexOptions.Compiled);

    public static void Main()
    {
        var list = new [] {
            "1.one",
            "2. two",
            "no number",
            "2.duplicate",
            "300. three hundred",
            "4-ignore this"
        };

        var distinctWithNumbers = list.Where(s => regex.IsMatch(s))
                                      .GroupBy(s => regex.Match(s).Groups["num"].Value)
                                      .Select(g => g.First());

        distinctWithNumbers.ToList().ForEach(Console.WriteLine);
        Console.ReadKey();
    }       
}

您可以尝试使用 this fiddle 中的方法

正如@orad 在评论中指出的,有一个 Linq 扩展 DistinctBy() 在 MoreLinq 中,可以用来代替分组,然后获取组中的第一项以消除重复项:
var distinctWithNumbers = list.Where(s => regex.IsMatch(s))
                              .DistinctBy(s => regex.Match(s).Groups["num"].Value);

试试看 this fiddle

编辑

如果你想使用你的比较器,你需要实现 GetHashCode所以它也使用这个表达式:
public int GetHashCode(T obj)
{
    return _expr.Invoke(obj).GetHashCode();
}

然后,您可以将比较器与 lambda 函数一起使用,该函数接受一个字符串并使用正则表达式获取数字:
var comparer = new GenericCompare<string>(s => regex.Match(s).Groups["num"].Value);
var distinctWithNumbers = list.Where(s => regex.IsMatch(s)).Distinct(comparer); 

我又创建了一个 fiddle用这种方法。

使用前瞻正则表达式

您可以将这两种方法中的任何一种与正则表达式一起使用 @"^\d+(?=\.)" .

只需更改获取“num”组的 lambda 表达式 s => regex.Match(s).Groups["num"].Value使用获取正则表达式匹配的表达式 s => regex.Match(s).Value
更新 fiddle here .

关于regex - 通过 linq 中的部分字符串区分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25513372/

相关文章:

python - 正则表达式匹配 MAC 地址

asp.net - 哪一种最适合 3 层架构; Linq to SQL 还是 Nhibernate?

c# - 在soundforge中运行C#脚本时出错

c# - 未使用 order by 时,Linq to objects join default order 是否指定?

regex - 我可以通过哪些方式改进这个正则表达式?

python - 如何使用 "contains"进行过滤?

java - 正则表达式删除最后一个括号内的内容

c# - 如何使用 Linq 在列表中找到对象?

c# - 使用 Linq 从数据表中获取不同的行(与多列不同)

c# - Linq 首先跳过 where (linq to objects)