C# Linq关键字提取-限制提取范围
关于C# Linq关键字提取-限制提取范围,c#,.net,linq,keyword,C#,.net,Linq,Keyword,关于 有没有办法限制要考虑的关键字数量?例如,我只想计算文本的前1000个单词。Linq中有一个“Take”方法,但它有不同的用途——所有的字都将被计算,N条记录将被返回。正确的替代方案是什么 只需在调用Split后直接应用Take: var results = src.Split() .Take(1000) .GroupBy(...) // etc 可枚举。Take实际上是流式输出结果;它不会完全缓冲其源代码,然后只返回前一
有没有办法限制要考虑的关键字数量?例如,我只想计算文本的前1000个单词。Linq中有一个“Take”方法,但它有不同的用途——所有的字都将被计算,N条记录将被返回。正确的替代方案是什么 只需在调用
Split
后直接应用Take
:
var results = src.Split()
.Take(1000)
.GroupBy(...) // etc
可枚举。Take
实际上是流式输出结果;它不会完全缓冲其源代码,然后只返回前一个N。不过,看看您原来的解决方案,问题是您要执行操作的输入是String.Split
。不幸的是,这种方法不使用任何类型的延迟执行;它急切地创建一个包含所有“拆分”的数组,然后返回它
因此,从某些文本中获取单词流序列的技术类似于:
var words = src.StreamingSplit() // you'll have to implement that
.Take(1000);
但是,我注意到您的查询的其余部分是:
...
.GroupBy(str => str) // group words by the value
.Select(g => new
{
str = g.Key, // the value
count = g.Count() // the count of that value
});
请注意,GroupBy
是一种缓冲操作-您可以预期,来自其源代码的所有1000个字最终都将存储在组输出过程中的某个位置
在我看来,这些选择是:
如果您不介意为了拆分目的浏览所有文本,那么src.Split().Take(1000)
就可以了。缺点是浪费时间(不再需要拆分后继续拆分)和浪费空间(即使只需要前1000个字,也要将所有字存储在一个数组中)。但是,查询的剩余部分将不会对超过需要的任何单词进行操作李>
如果由于时间/内存限制,您负担不起(1),请使用src.StreamingSplit().Take(1000)
或同等工具。在这种情况下,在找到1000个单词后,将不会处理任何原始文本李>
请注意,在这两种情况下,这1000个单词本身最终都会被GroupBy
子句缓冲。严格地说,LINQ不一定会阅读所有内容;Take将尽快停止。问题是,在相关的问题中,您看到的是计数,在不消耗所有数据的情况下,很难获得计数。同样,string.Split将查看所有内容
但是,如果您编写了一个惰性非缓冲剥离函数(使用yield-return),并且希望得到前1000个唯一单词,那么
var words = LazySplit(text).Distinct().Take(1000);
将工作Take()
是一个懒惰的函数!这并不是说所有的单词都要经过计算。参见示例。简单的解决方案,但在我的案例中似乎效果良好。谢谢你,乔恩!感谢您的详细回复。