- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个方法可以跨文件执行简单的“grep”,使用可枚举的“搜索字符串”。 (实际上,我正在做一个非常天真的“查找所有引用”)
IEnumerable<string> searchStrings = GetSearchStrings();
IEnumerable<string> filesToLookIn = GetFiles();
MultiMap<string, string> references = new MultiMap<string, string>();
foreach( string fileName in filesToLookIn )
{
foreach( string line in File.ReadAllLines( fileName ) )
{
foreach( string searchString in searchStrings )
{
if( line.Contains( searchString ) )
{
references.AddIfNew( searchString, fileName );
}
}
}
}
备注:MultiMap<TKey,TValue>
与Dictionary<TKey,List<TValue>>
大致相同,只是避免了您通常会遇到的 NullReferenceExceptions。
我一直在尝试使用链接的 LINQ 扩展方法将它变成更“功能”的样式,但还没有弄清楚。
一次死胡同尝试:
// I get lost on how to do a loop within a loop here...
// plus, I lose track of the file name
var lines = filesToLookIn.Select( f => File.ReadAllLines( f ) ).Where( // ???
还有一个(希望这次保留文件名):
var filesWithLines =
filesToLookIn
.Select(f => new { FileName = f, Lines = File.ReadAllLines(f) });
var matchingSearchStrings =
searchStrings
.Where(ss => filesWithLines.Any(
fwl => fwl.Lines.Any(l => l.Contains(ss))));
但我似乎仍然丢失了我需要的信息。
也许我只是从错误的角度来处理这个问题?从性能的角度来看,循环应该按照与原始示例大致相同的顺序执行。
关于如何在更紧凑的函数表示中做到这一点有什么想法吗?
最佳答案
怎么样:
var matches =
from fileName in filesToLookIn
from line in File.ReadAllLines(fileName)
from searchString in searchStrings
where line.Contains(searchString)
select new
{
FileName = fileName,
SearchString = searchString
};
foreach(var match in matches)
{
references.AddIfNew(match.SearchString, match.FileName);
}
编辑:
从概念上讲,查询将每个文件名转换为一组行,然后将该组行交叉连接到一组搜索字符串(意味着每一行都与每个搜索字符串配对)。该集合被过滤为匹配行,并选择每行的相关信息。
多个from
子句类似于嵌套的foreach
语句。每个都表示前一个范围内的新迭代。多个 from
子句转换为 SelectMany
方法,从每个元素中选择一个序列,并将结果序列展平为一个序列。
C# 的所有查询语法都转换为扩展方法。然而,编译器确实使用了一些技巧。一种是使用匿名类型。每当 2+ 范围变量在同一范围内时,它们可能是幕后匿名类型的一部分。这允许任意数量的作用域数据流过扩展方法,如 Select
和 Where
,它们具有固定数量的参数。参见 this post了解更多详情。
下面是上述查询的扩展方法翻译:
var matches = filesToLookIn
.SelectMany(
fileName => File.ReadAllLines(fileName),
(fileName, line) => new { fileName, line })
.SelectMany(
anon1 => searchStrings,
(anon1, searchString) => new { anon1, searchString })
.Where(anon2 => anon2.anon1.line.Contains(anon2.searchString))
.Select(anon2 => new
{
FileName = anon2.anon1.fileName,
SearchString = anon2.searchString
});
关于c# - 如何使用 LINQ 使 C# 'grep' 更具功能性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1122084/
我的按钮有问题。该按钮是登录按钮。当我在输入凭据后单击回车时,将触发查看凭据是否正确的方法。这没有任何问题。 但还应该发生的是,在检查这些凭据是否正确之后,登录和注册按钮应该会被删除,同时会出现一个新
因此,我尝试以 Angular 显示多个 View ,以帮助解决我正在构建的网站中遇到的页脚问题。我想确保我一直在阅读和尝试模仿的内容是有意义的。这就是我到目前为止所拥有的。 index.html
我正在尝试创建可调整大小的 div 容器,而且它们是可拖动的。 我使用了 Angular Material 拖放和 angular resizable element 这是解决方法 https://s
我正在尝试创建可调整大小的 div 容器,而且它们是可拖动的。 我使用了 Angular Material 拖放和 angular resizable element 这是解决方法 https://s
我是一名优秀的程序员,十分优秀!