えムナウ Blog

えムナウ の なすがまま

目次

Blog 利用状況

ニュース


follow mnow at http://twitter.com


えムナウのプログラミングのページ

INETAJ

書庫

日記カテゴリ

ギャラリ

Linqはすごい? その5

Linqはすごい? その4の回答編といますか、その5です。
4回(15, 13, 12, 17) です。

メソッドで書き直してみました。

あと従来の技術で書いた例もあげておきます。
Accoutクラスも作る必要があります。
foreachは2回なのですが、SortedListを使っている時点で内部でループしているでしょうが・・・

 

では今までの解説をします。

その1では私がLinqの説明時にいつも使っているクエリをforeachで書きなおしてみました。
おそらく皆さんも今まで書いていたんであろうコードです。
これによってLinqというのはforeachの置き換えだよって気づいてほしかったのです。
Linqはすごい? その1

その2ではそれ(Linqというのはforeachの置き換え)を強調するためにあえて速度比較をしてみました。
その結果ですが多くの方は4倍以上違うのが当たり前のコードをすんなりと受け入れてしまいました。
Linqはすごい? その2

その3ではマイクロソフトのExtensionに似せたコードを作成して4倍以上違う根拠を見せようとしました。
あんまり似ていたので「コード出すのやばいんじゃ」って意見もありましたがあくまで挙動を調べた私のオリジナルです。
Linqはすごい? その3

つまり、一貫してこのシリーズで言いたかったことは「linqというのはforeachの置き換えの技術である」という見過ごされがちな一面です。

その4やその5ではじゃ、どんなふうに置き換わっているのって話です。
Linqはすごい? その4

public class Account

{

    public string Name { get; set; }

    public int No { get; set; }

    public string Prefecture { get; set; }

};

public class Descending : Comparer<int>

{

    public override int Compare(int x, int y)

    {

        return y - x;

    }

};

 

var al = new Account[] {

    new Account{Name="とっちゃん",Prefecture="1東京",No=13},

    new Account{Name="むたぐちさん",Prefecture="2大阪",No=17},

    new Account{Name="επιστημηさん",Prefecture="1東京",No=12},

    new Account{Name="中さん",Prefecture="2大阪",No=1},

    new Account{Name="えムナウ",Prefecture="1東京",No=15}

};

{

    var accounts = al.Where(a => a.No > 10)

        .OrderByDescending(a => a.No)

        .GroupBy(a => a.Prefecture)

        .OrderBy(accPref => accPref.Key);

 

    foreach (var accgroup in accounts)

        foreach (var account in accgroup)

            Console.WriteLine(account.No.ToString() + "," + account.Name + "(" + account.Prefecture + ")");

}

{

    Descending descendingSort = new Descending();

    SortedList<int, Account> sortedAccounts = new SortedList<int, Account>(descendingSort);

    foreach (var a in al)

    {

        if (a.No > 10)

        {

            sortedAccounts.Add(a.No, a);

        }

    }

    SortedList<string, List<Account>> accounts = new SortedList<string, List<Account>>();

    foreach (var s in sortedAccounts)

    {

        List<Account> accountList;

        if (accounts.TryGetValue(s.Value.Prefecture, out accountList))

        {

            accountList.Add(s.Value);

 

        }

        else

        {

            accountList = new List<Account>();

            accountList.Add(s.Value);

            accounts.Add(s.Value.Prefecture, accountList);

        }

    }

    foreach (var accgroup in accounts)

        foreach (var account in accgroup.Value)

            Console.WriteLine(account.No.ToString() + "," + account.Name + "(" + account.Prefecture + ")");

}

 

投稿日時 : 2008年1月27日 15:47

コメントを追加

# re: Linqはすごい? その5 2008/01/27 21:12 nsharp

※反論ではないのでご安心ください。w

非LINQ版のソースを見てて思い浮かんだことは、LINQの持つ遅延性です。

上記2つのソースを比べてみると、並べ替えが行われるタイミングが異なってます。
(非LINQ版では sortedAccounts の並べ替えだけが早めに実行されてしまう。)

LINQに限った話ではありませんけど、どこで何が行われるのかを正確に把握するのは疲れますね・・・。(;´Д`)

# re: Linqはすごい? その5 2008/01/28 15:02 siokoshou

foreach置き換えなのはわかっていても
>4倍以上違うのが当たり前
これには気づいていませんでした。.NETの特徴っぽいですね。IEnumerable<T> の foreach だから差が出るのかと思ったら、int[] の foreach でも差が出ますね。この事実が最大の収穫でした。

C も一緒?と思って、ループ1回:中で計算2つ、とループ2回:それぞれ計算1つを比べてみるとほぼ同じ速さでした。念のためループ1回:計算1つと時間差がはっきり出ることも確認してます。

でも、その2の cal1 と cal3 の速さの差は foreach の数では説明がつきませんよね…。キャッシュに載る載らないやループ回数でどちらが速いかさえ変わってますし。

>どこで何が行われるのかを正確に把握するのは疲れますね
難しいですね…。特に .NET は…。

# re: Linqはすごい? その5 2008/01/29 1:32 えムナウ

nsharp さん
siokoshou さん
ありがとうございます。

他のBlogでのコメントのご活躍は存じております。

siokoshou さんのBlogも読ませていただいてます。

次回からはLinq to SQLに入ります。
これからもよろしくお願いします。

# re: Linqはすごい? その5 2008/01/29 1:36 えムナウ

>LINQの持つ遅延性
Linqはパイプラインですので。
一括処理という意味では遅延性があるともいえますね。

>ループ1回:中で計算2つ、とループ2回:それぞれ計算1つを比べてみるとほぼ同じ速さでした。
うーん、ループ2回のほうが遅そうですけどねぇ。

>どこで何が行われるのかを正確に把握するのは疲れますね
一度正確にやっておくと後が楽な気がします。

# re: Linqはすごい? その5 2008/01/29 6:44 siokoshou

>siokoshou さんのBlogも読ませていただいてます。
ありがとうございます。こちらこそよろしくお願いします(^^)

>うーん、ループ2回のほうが遅そうですけどねぇ。
あ、C のほう、デバッグ版で動かしてました(汗)
最適化するとやはりループ2回のほうが遅いですね(精度の悪いマイクロベンチ程度なのでループ回数で差がだいぶ変わりますが)。

そして自分の頭の中では、ループカウンタの操作が増える点の考慮が漏れてたことに気づきました。不注意すぎ>自分
それにしても C と比べると .NET はループの数でストレートに伸びすぎすぎですねぇ。

# re: Linqはすごい? その5 2008/01/29 8:05 nsharp

> 一度正確にやっておくと後が楽な気がします。

ええ。LINQに関して言えば、標準クエリ演算子(代表的なもの)を自前で実装してみるのは誰もが通る道ではないかと思います。w

で、最難関のOrderBy/ThenByを無事クリアできれば、もう怖いものはほとんどありません。w

タイトル
名前
URL
コメント