Estoy tratando de aprender un poco más sobre LINQ implementando el spelling corrector de Peter Norvig en C#.Método LINQ para agregar elementos a un diccionario
La primera parte consiste en tomar una gran file of words (alrededor de 1 millón) y ponerlo en un diccionario en el que el key
es la palabra y la value
es el número de ocurrencias.
Me suelo hacer esto de esta manera:
foreach (var word in allWords)
{
if (wordCount.ContainsKey(word))
wordCount[word]++;
else
wordCount.Add(word, 1);
}
Dónde allWords
es un IEnumerable<string>
En LINQ actualmente estoy haciendo de esta manera:
var wordCountLINQ = (from word in allWordsLINQ
group word by word
into groups
select groups).ToDictionary(g => g.Key, g => g.Count());
comparo la 2 diccionarios mirando todos los <key, value>
y son idénticos, por lo que están produciendo los mismos resultados.
El bucle foreach
toma 3,82 segundos y la consulta LINQ toma 4.49 segundos
estoy de sincronización utilizando la clase Cronómetro y estoy funcionando en modo de lanzamiento. No creo que el rendimiento sea malo. Me preguntaba si había alguna razón para la diferencia.
¿Estoy haciendo la consulta LINQ de forma ineficiente o me falta algo?
Actualización: aquí está el ejemplo de código de referencia completo:
public static void TestCode()
{
//File can be downloaded from http://norvig.com/big.txt and consists of about a million words.
const string fileName = @"path_to_file";
var allWords = from Match m in Regex.Matches(File.ReadAllText(fileName).ToLower(), "[a-z]+", RegexOptions.Compiled)
select m.Value;
var wordCount = new Dictionary<string, int>();
var timer = new Stopwatch();
timer.Start();
foreach (var word in allWords)
{
if (wordCount.ContainsKey(word))
wordCount[word]++;
else
wordCount.Add(word, 1);
}
timer.Stop();
Console.WriteLine("foreach loop took {0:0.00} ms ({1:0.00} secs)\n",
timer.ElapsedMilliseconds, timer.ElapsedMilliseconds/1000.0);
//Make LINQ use a different Enumerable (with the exactly the same values),
//if you don't it suddenly becomes way faster, which I assmume is a caching thing??
var allWordsLINQ = from Match m in Regex.Matches(File.ReadAllText(fileName).ToLower(), "[a-z]+", RegexOptions.Compiled)
select m.Value;
timer.Reset();
timer.Start();
var wordCountLINQ = (from word in allWordsLINQ
group word by word
into groups
select groups).ToDictionary(g => g.Key, g => g.Count());
timer.Stop();
Console.WriteLine("LINQ took {0:0.00} ms ({1:0.00} secs)\n",
timer.ElapsedMilliseconds, timer.ElapsedMilliseconds/1000.0);
}
No es posible comentar la diferencia a menos que publique el código de referencia. – JaredPar
Acabo de agregar eso a la pregunta por ti. –