我第一次尝试使用LINQ,并决定尝试基本的人类语言识别。输入文本将针对语言中最常见的10,000个单词的HashSet
进行测试,并获得分数。
我的问题是,LINQ查询有更好的方法吗?也许是我不知道的另一种形式?它有效,但我相信这里的专家将能够提供更清洁的解决方案!
public PolyAnalyzer() {
Dictionaries = new Dictionary<string, AbstractDictionary>();
Dictionaries.Add("Bulgarian", new BulgarianDictionary());
Dictionaries.Add("English", new EnglishDictionary());
Dictionaries.Add("German", new GermanDictionary());
Dictionaries.Values.Select(n => new Thread(() => n.LoadDictionaryAsync())).ToList().ForEach(n => n.Start());
}
public string getResults(string text) {
int total = 0;
return string.Join(" ",
Dictionaries.Select(n => new {
Language = n.Key,
Score = new Regex(@"\W+").Split(text).AsQueryable().Select(m => n.Value.getScore(m)).Sum()
}).
Select(n => { total += n.Score; return n; }).
ToList().AsQueryable(). // Force immediate evaluation
Select(n =>
"[" + n.Score * 100 / total + "% " + n.Language + "]").
ToArray());
}
P.S。我知道这是一种非常简单的语言识别方法,我只对LINQ方面感兴趣。
答案 0 :(得分:4)
我会像这样重构它:
public string GetResults(string text)
{
Regex wordRegex = new Regex(@"\W+");
var scores = Dictionaries.Select(n => new
{
Language = n.Key,
Score = wordRegex.Split(text)
.Select(m => n.Value.getScore(m))
.Sum()
});
int total = scores.Sum(n => n.Score);
return string.Join(" ",scores.Select(n => "[" + n.Score * 100 / total + "% " + n.Language + "]");
}
几点:
AsQueryAble()
是不必要的 -
这是Linq to Objects的全部内容
是IEnumerable<T>
- 足够好。
删除了一些ToList()
- 也
不必要的,避免急切加载
不需要时的结果。
虽然它只有一个LINQ很好 查询这不是竞争 - 目标 为了整体可读性并考虑如何 你(和其他人)必须维护代码。我将您的查询分成三个更易读(imo)的部分。
一定要避免副作用
可能 - 我删除了你的那个
到变量total
- 它是
令人困惑的 - LINQ查询不应该
有副作用,因为两次运行相同的查询可能会产生不同的结果。在您的情况下,您可以在单独的Linq查询中计算总计。
不要重新新建或重新计算Linq中的变量
投影如果没有必要 - 我
从Linq中删除了正则表达式
查询并初始化变量
一旦在外面 - 否则你就是
重新创建Regex实例N
次
而不只是一次。根据查询,这可能会产生巨大的性能影响。
答案 1 :(得分:1)
我认为您发布的代码非常令人困惑。我已经重写了它,我认为它会给你相同的结果(当然我无法测试它,实际上我认为你的代码有一些错误的部分)但它现在应该更加简洁。如果这不正确,请告诉我。
public PolyAnalyzer()
{
Dictionaries = new Dictionary<string, AbstractDictionary>();
Dictionaries.Add("Bulgarian", new BulgarianDictionary());
Dictionaries.Add("English", new EnglishDictionary());
Dictionaries.Add("German", new GermanDictionary());
//Tip: Use the Parallel library to to multi-core, multi-threaded work.
Parallel.ForEach(Dictionaries.Values, d =>
{
d.LoadDictionaryAsync();
});
}
public Dictionary<string, int> GetResults(string text)
{
//1) Split the words.
//2) Calculate the score per dictionary (per language).
//3) Return the scores.
string[] words = new Regex(@"\w+").Split().ToArray();
Dictionary<string, int> scores = this.Dictionaries.Select(d => new
{
Language = d.Key,
Score = words.Sum(w => d.Value.GetScore(w))
}));
return scores;
}