After screwing around with a false start (yield return in the key selector lambda of ToDictionary- disallowed by the compiler), I came up with something really gross-looking using Aggregate. Then I posed the problem to a couple of coworkers. Here's what we all came up with. Which one do you think runs the fastest? The answer may surprise you.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<string> input = new List<string> { "1", "2", "3", "4", "5", "6" };
// #1: Matt's original with local var
var sw1 = Stopwatch.StartNew();
for (int i = 0; i < 4000000; i++)
{
int index = 0;
var dic = input.ToDictionary(k => index++);
}
sw1.Stop();
// #2: Matt's "yikes" version with .Aggregate
var sw2 = Stopwatch.StartNew();
for (int i = 0; i < 4000000; i++)
{
var dic = input.Aggregate(
new { Index = 0, Dictionary = new Dictionary() },
(a, t) => { a.Dictionary.Add(a.Index, t); return new { Index = a.Index + 1, Dictionary = a.Dictionary }; }
);
}
sw2.Stop();
// #3: James' "list ordinal hack" version
var sw3 = Stopwatch.StartNew();
for (int i = 0; i < 4000000; i++)
{
var dic2 =
input.Aggregate(new List<int>(), (lst, elt) => { lst.Add(lst.Count); return lst; })
.ToDictionary(k => k, v => input[v]);
}
sw3.Stop();
// #4: James' "nasty list hack + .Aggregate" version
var sw4 = Stopwatch.StartNew();
for (int i = 0; i < 4000000; i++)
{
var dic =
input.Aggregate(new Dictionary<int, string>(), (d, elt) => { d[d.Count] = elt; return d; });
}
sw4.Stop();
Console.WriteLine("Done. 1:{0}ms, 2:{1}ms, 3:{2}ms, 4:{3}ms", sw1.ElapsedMilliseconds, sw2.ElapsedMilliseconds, sw3.ElapsedMilliseconds, sw4.ElapsedMilliseconds);
Console.ReadKey();
}
}
}
No comments:
Post a Comment