このクソサンプルコードを書いたのは誰だ!レベル。こんなのがMSDNに乗ってるとは…… 方法: LINQ クエリのカスタム メソッドを追加する URL
2013-07-02 23:21:53 via web
ノイエ先生が突然きれてたので、試してみました。前半がMSDNからのこぴぺ。後半が自分なりになおしてみたやつ。
static class LINQExtension { public static double Median(this IEnumerable<double> source) { if (source.Count() == 0) { throw new InvalidOperationException("Cannot compute median for an empty set."); } var sortedList = from number in source orderby number select number; int itemIndex = (int)sortedList.Count() / 2; if (sortedList.Count() % 2 == 0) { // Even number of items. return (sortedList.ElementAt(itemIndex) + sortedList.ElementAt(itemIndex - 1)) / 2; } else { // Odd number of items. return sortedList.ElementAt(itemIndex); } } public static double MedianEx(this IEnumerable<double> source) { var items = source.OrderBy(d => d).ToArray(); if (!items.Any()) { throw new InvalidOperationException("Cannot compute median for an empty set."); } int itemIndex = items.Length / 2; if (items.Length % 2 == 0) { return (items[itemIndex] + items[itemIndex - 1]) / 2; } else { return items[itemIndex]; } } }
Ix-MainをNuGetで参照にくわえて10000個くらいのdoubleの配列に対して1000回くらいループ回してみて時間はかってみました。
var source = EnumerableEx.Generate(0.0, d => d <= 10000.0, d => ++d, d => d); { var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < 1000; i++) { source.Median(); } stopwatch.Stop(); Console.WriteLine("Median: {0}ms", stopwatch.ElapsedMilliseconds); } { var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < 1000; i++) { source.MedianEx(); } stopwatch.Stop(); Console.WriteLine("MedianEx: {0}ms", stopwatch.ElapsedMilliseconds); }
Median: 7290ms MedianEx: 2538ms
ふむ2倍以上遅い。
ということで、何故遅いのかは夜遅いので誰かにパス・・・!