SelectMany枚举按字符串值需要索引过滤的多个文件

时间:2019-05-08 19:50:23

标签: c# linq

我有一个C#LINQ查询,该查询接收许多文件,并枚举每个文件以查找“风险字符串”。当每个文件都找到一个“风险字符串”时,我需要将文件名作为键保存到字典中,找到的行号作为数组保存到字典值中(发现的“风险”会多次出现每个文件的字符串)。我似乎无法弄清楚如何从查询中获取行号。当前,它所做的只是从0开始并在每次找到字符串时计数,然后将实际行号本身保存到数组中。

帮助!

var files = Directory.EnumerateFiles(srcPath, "*", SearchOption.AllDirectories)
                .Where(s => s.EndsWith(riskFileType))
                .SelectMany(File.ReadLines, (file, line) => new {file, line}).Distinct()
                .Where(@t => filterStringExpression.IsMatch(t.line))
                .Select((@t, index) => new {File = @t.file, Line = @t.line, index}).Distinct()
                .GroupBy(q => q.File)
                .ToDictionary(g => g.Key, g => g.Select(q => q.index)
                .ToArray());

当前输出:

Namespace risk strings were found on the below classes, please review the results.
..\..\src\classes\BookingCls.cls risk found on lines:  0,  1,  2, 
..\..\src\classes\BookingDaySnapshotCls.cls risk found on lines:  3, 
..\..\src\classes\BookingEventCls.cls risk found on lines:  4,  5, 
..\..\src\classes\BookingOwnerChangeExt.cls risk found on lines:  6,  7,  8, 
..\..\src\classes\BookingSourceChangeExt.cls risk found on lines:  9,  10,  11, 
..\..\src\classes\GuestroomTypeDayCls.cls risk found on lines:  12, 

1 个答案:

答案 0 :(得分:1)

我将在加载文件时分配行号。

var files = Directory.EnumerateFiles(srcPath, "*", SearchOption.AllDirectories)
    .Where(s => s.EndsWith(riskFileType))
    .SelectMany(
        file => File.ReadLines(file).Select((line, index) => new {line, rowNumber = index + 1}), 
        (file, line) => new {file, line.line, line.rowNumber})
    .Where(@t => filterStringExpression.IsMatch(t.line))
    .GroupBy(q => q.file)
    .ToDictionary(g => g.Key, g => g.Select(q => q.rowNumber))
    .ToArray();

这只是替代查询:

var files = Directory.EnumerateFiles(srcPath, "*", SearchOption.AllDirectories)
    .Where(s => s.EndsWith(riskFileType))
    .SelectMany(
        file => File.ReadLines(file).Select((line, index) => new {line, rowNumber = index + 1}), 
        (file, line) => new {file, line.line, line.rowNumber})
    .Where(@t => filterStringExpression.IsMatch(t.line))
    .ToLookup(k => k.file, e => e.rowNumber);