I am a little puzzled. The PO asked to improve the solution with Linq. Benchmarking the solutions I received the following result in the table (code see below). Unless I am missing something (in which case I'd appreciate comments) I cannot see that Linq improves the simple solution with the for-loop.
Result: the for loop is a lot faster and needs less memory.
Consequence: I would keep the simple for-loop. The argument of Conciseness that favors Linq does not apply here because the code is hidden away in a method. And the performance is not better but worse.
I like Linq. Tried to work without it, recently, and failed. But it is not always better.
Method |
Mean |
Error |
StdDev |
Gen 0 |
Allocated |
RunLinqZip |
1,179.16 ns |
2.362 ns |
1.844 ns |
0.1831 |
1,152 B |
RunLinqRange |
556.54 ns |
1.359 ns |
1.135 ns |
0.1726 |
1,088 B |
RunForLoop |
63.84 ns |
0.101 ns |
0.094 ns |
- |
- |
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace Benchmarks
{
public class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<MemoryBenchmarkerDemo>();
}
}
[MemoryDiagnoser]
public class MemoryBenchmarkerDemo
{
public string[] Id = new string[] { "ATTR", "TAL", "SPELL", "LITURGY", "REGENERATE", "INI", "CT_9", "CT_9/ITEMTEMPLATE_231" };
public string[] Att = new string[] { "ATTR_2", "TAL_99", "SPELL_232", "LITURGY_123", "REGENERATE", "INI", "CT_9", "CT_9/ITEMTEMPLATE_231" };
public int FitnessFor(string individual, string target)
{
int sum = 0;
for (int i = 0; i < Math.Min(individual.Length, target.Length); i++)
if (individual[i] == target[i]) sum++;
return sum;
}
public int FitnessRange(string individual, string target)
{
return Enumerable.Range(0, individual.Length)
.Count(i => individual[i] == target[i]);
}
public int FitnessZip(string individual, string target)
{
return individual.Zip(target).Count(pair => pair.Item1 == pair.Item2);
}
[Benchmark]
public void RunLinqZip()
{
for(int i = 0; i< Id.Length; i++)
{
FitnessZip(Id[i], Att[i]);
}
}
[Benchmark]
public void RunLinqRange()
{
for (int i = 0; i < Id.Length; i++)
{
FitnessRange(Id[i], Att[i]);
}
}
[Benchmark]
public void RunForLoop()
{
for (int i = 0; i < Id.Length; i++)
{
FitnessFor(Id[i], Att[i]);
}
}
}
}