我知道了这个问题:
return ngrms.GroupBy(x => x)
.Select(s => new { Text = s.Key, Count = s.Count() })
.Where(x => x.Count > minCount)
.OrderByDescending(x => x.Count)
.ToDictionary(g => g.Text, g => g.Count);
ngrms是IEnumerable<String>
有没有一种方法可以优化此代码? 我不在乎是否必须重写所有代码并进行所有低级调整。
答案 0 :(得分:3)
如果实现的Dictionary
可以递增(模拟多集或袋),则可以比LINQ快约3倍,但是除非您有很多ngrms
,否则相差很小。在1000万列表中,LINQ代码在我的PC上花费了不到一秒钟的时间,并且具有大约100个唯一值。如果您的LINQ代码花费时间1,则foreach
和Dictionary<string,int>
花费0.85,而这段代码花费0.32。
这是在Dictionary
中创建可更新值的类:
public class Ref<T> {
public T val { get; set; }
public Ref(T firstVal) => val = firstVal;
public static implicit operator T(Ref<T> rt) => rt.val;
}
(如果C#允许operator ref T
,则可以将ref
返回到val
属性,并且几乎将Ref<T>
视为{{1}类型的左值}。
现在,您可以计算T
中每个字符串的出现次数,而每个字符串只需查找一次即可。
Dictionary<string,Ref<int>>
最后,您可以通过将计数过滤到要保留的计数来计算答案:
var dictCounts = new Dictionary<string, Ref<int>>();
foreach (var s in ngrms) {
if (dictCounts.TryGetValue(s, out var refn))
++refn.val;
else
dictCounts.Add(s, new Ref<int>(1));
}
答案 1 :(得分:1)
通过linq查询,您可以考虑使用简单的foreach
循环来重写代码,以获得更好的性能,如下所示。执行需要o(n)
的时间复杂度:
Dictionary<string, int> dict = new Dictionary<string, int>();
foreach(var s in ngrms)
{
if (dict.ContainsKey(s))
dict[s]++;
else
dict.Add(s, 1);
}
return dict.Where(a => a.Value > minCount);