【C#】System.Linq.Enumerable.GroupByを絵で表現してみた。

  • 2012.04.07 Saturday
  • 20:07

System.Linq.Enumerable.GroupByメソッドの振る舞いを絵で表現してみました。
やっぱり絵にすると頭の中で何かが・・・・なんていうんだろうね〜。
結局、結論は理解が深まったといえる。たぶんだけど・・・。

GroupByは、シーケンスに対して、何らかのルールを適用することで新しい構造を作ります。SelectManyは、既存の構造を、破壊してシーケンスにするので、操作は全く逆になります。

SelectManyを絵で描くと



GroupByした後にSelectManyするとソートを書けた事になるね。
今回の場合は順序は色が見つかった順。
順序を制御したいならOrderBy!


追記)
GrougByしてSelectManyした時の結果も絵にしてみました。

【C#】はじめてのParallel.For

  • 2011.05.24 Tuesday
  • 23:52
JUGEMテーマ:コンピュータ


そういえば使ったことなかったのでコードを書いてみた。

using System;
using System.Threading.Tasks;

namespace ParallelForDemo20110524_001
{
 class Program
 {
  static void Main(string[] args)
  {
   Parallel.For(0, 100, Console.WriteLine);
  }
 }
}


具体的な実行結果は予想できないけど、思った通りに動いてるみたい。 

【C#】IEnumeratorを継承したクラスがない。

  • 2011.05.15 Sunday
  • 13:22
JUGEMテーマ:コンピュータ


    class Program
    {
        static void Main()
        {
            var list = new MyList<int> { 1, 2, 3 };

            IEnumerator current = list.GetEnumerator();
            while (current.MoveNext())
            {
                Console.WriteLine(current.Current);
            }
        }
    }

    public class MyList<T> : IEnumerable<T>
    {
        private ListNode<T> _first;
        private ListNode<T> _last;

        public void Add(T value)
        {
            var node = new ListNode<T> { Value = value };
            if (_first == null)
                _first = _last = node;
            else
                _last = _last.Next = node;
        }

        private IEnumerable<T> GetEnumerable()
        {
            for (ListNode<T> currentNode = _first; currentNode != null; currentNode = currentNode.Next)
            {
                yield return currentNode.Value;
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return GetEnumerable().GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerable().GetEnumerator();
        }
    }

    class ListNode<TK>
    {
        public TK Value { get; set; }
        public ListNode<TK> Next { get; set; }
    }

上記のコードはhttp://pro.art55.jp/?eid=1303805で紹介したコードを動的なものから静的なものに変換して、さらにIEnumerableを継承させたものです。一部メソッドが消えていたりして微妙に違うところもありますが、大体同じです。

このコードを書き終えて気づきました。IEnumerator インターフェースを継承したクラスを自分で実装していないことに・・・。「あれ?実装しなくてもいけるの?」と、狐につままれた気分です。そもそも元々書いてたコードにはIEnumerableを継承したクラスすらなかった訳ですが・・・・

yield return当たりがなんだかがんばってくれているのだとは思いますが、狐はどこにいるんでしょうか・・・調べる価値がありそうです。

コンパイル後のILをみるとかyield returnを使わずに記述してみるとか

そのへんを探ってみたら答えが出そうな気が済ます(やってませんが・・・)

以前の投稿を探してみるとListを自作しているコードを見つけました。
http://pro.art55.jp/?eid=1175888

using System.Collections;
using System.Collections.Generic;

namespace Art55.Lib
{
 public class C<T> : IEnumerable<T>
 {
  public void Add(T value)
  {
   ListNode<T> tail = ListItemUtil<T>.GetTail(_head);
   if (_head == null)
    _head = new ListNode<T>(value);
   else
    tail.Next = new ListNode<T>(value);
  }

  public IEnumerator<T> GetEnumerator()
  {
   return new E<T>(_head);
  }

  IEnumerator IEnumerable.GetEnumerator()
  {
   foreach (var item in this)
    yield return item;
  }

  private ListNode<T> _head;
 }

 internal class E<T> : IEnumerator<T>
 {
  public E(ListNode<T> item)
  {
   _top = item;
  }

  public bool MoveNext()
  {
   if (_current == null)
    Reset();
   else
    _current =_current.Next;
   return _current != null;
  }

  public void Reset()
  {
   _current = _top;
  }

  public T Current
  {
   get { return _current.Value; }
  }

  object IEnumerator.Current
  {
   get { return Current; }
  }

  public void Dispose()
  {
  }

  private readonly ListNode<T> _top;
  private ListNode<T> _current;
 }

 internal class ListNode<T>
 {
  public ListNode(T value)
  {
   Value = value;
  }

  internal protected ListNode<T> Next { get; set; }
  public T Value { get; private set; }
 }

 static class ListItemUtil<T>
 {
  public static ListNode<T> GetTail(ListNode<T> head)
  {
   if (head == null)
    return null;
   while (head.Next != null)
    head = head.Next;
   return head;
  }
 }
}


internal class E<T> : IEnumerator<T>を一生懸命自作しているわけですが、実はいらなかったんですね。

【C#】最近よくつかうTuple

  • 2011.05.14 Saturday
  • 22:47
JUGEMテーマ:コンピュータ

最近よくTupleにお世話になっています。
Tupleの実装自体さほど難しくないとは思うのですが
標準ライブラリーとして、もっと早く組み込まれていればなーって思ったりしてます。

知恵がたりなかった為
キーとなる情報をわざわざ構造体やクラスを作ったり
複数キーを文字列で連結させ、キーがぶつからないかな−ってどきどきしてみたり
アホな事をしてたなーって今更ながらに思ってます。

【C#】【dynamic】クラスを定義せず実行時にオブジェクトに役割を与える。

  • 2011.05.13 Friday
  • 22:55
JUGEMテーマ:コンピュータ


あいわからずDictionary<T, K>をラップしたDynamicObjecctを使用してプログラミングを
してみたぞ(遊んでみた)という内容を投稿したいと思います。

今日、作ろうと思うのは下記のような構造をもつオブジェクトです。



クラスを定義せずに、プログラミングをしようとした場合に
一番に考えたのが、このようなオブジェクト図(もどき)でした。
上記は4つのノードを追加した状況にある場合のスナップショットです。

これにたいしてクライアント(ProgramクラスのMainの処理)は
今回は2つのメッセージを送りたいと思っています。

1. 値を追加する
2. 列挙する

Mainの処理を書いてみると

    static void Main(string[] args)
    {
      dynamic list = CreateList();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      foreach (int value in list.GetEnumerable())
      {
        Console.WriteLine(value);
      }
    }

このコードがは私の希望です。
前回までは、下記のように書いてました。

    static void Main(string[] args)
    {
      dynamic list = CreateList();
      Add(list, 1);
      Add(list, 2);
      Add(list, 3);

      foreach (int value in GetEnumerable(list))
      {
        Console.WriteLine(value);
      }
    }

listオブジェクトにメッセージを送りたいので
なるべくなら

Add(list, 1);

ではなく

list.Add(1);

と記述したいわけです。要するにカリー化したいんです(←よくわからない言葉を使うのは気がひけます)

list.Method(...)と記述するといかにもオブジェクトがもつメソッドを呼び出したように見えます。



是非とも記述したい。
そこで、今回は一工夫いれながらコードを書いてみました。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;

namespace Art55.DynamicNamedPropertyObjectDemo001
{
  class Program
  {
    static void Main()
    {
      dynamic list = CreateList();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      foreach (int value in list.GetEnumerable())
      {
        Console.WriteLine(value);
      }
    }

    static dynamic CreateList()
    {
      dynamic list = NamedDynamicObject.Create();
      list.First = null;
      list.Last = null;
      list.Add = new Action<object>(value => Add(list, value));
      list.GetEnumerable = new Func<IEnumerable>(() => GetEnumerable(list));
      return list;
    }

    static void Add(dynamic list, object value)
    {
      dynamic node = CreateListNode(value);
      if (list.First == null)
        list.First = list.Last = node;
      else
        list.Last = list.Last.Next = node;
    }

    static IEnumerable GetEnumerable(dynamic list)
    {
      for (dynamic currentNode = list.First; currentNode != null; currentNode = currentNode.Next)
      {
        yield return currentNode.Value;
      }
    }

    static dynamic CreateListNode(object value)
    {
      dynamic node = NamedDynamicObject.Create();
      node.Value = value;
      node.Next = null;
      return node;
    }
  }

  public class NamedDynamicObject : DynamicObject
  {
    public static dynamic Create()
    {
      return new NamedDynamicObject();
    }

    protected NamedDynamicObject()
    {
      _setting = new Dictionary<string, object>();
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      return _setting.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
      _setting[binder.Name] = value;
      return true;
    }

    private readonly Dictionary<string, object> _setting;
  }
}

CreateList()メソッドでListの能力を全て構築させます。こうすることで、CreateListの戻り値のオブジェクトはすでにListな振る舞いをするオブジェクトとなっているわけです。CreateList()
メソッドが呼ばれたあとの処理は、全てlistにたいしてメッセージを送るだけで、要求が満たされるようになるわけです。こうすることでListオブジェクトが管理しているListNode達の存在や構造を意識することもなくりました。

心残りは

list.Add = new Action<object>((value) => Add(list, value));

こういうのが、もう少しわかりやすくかけないかなーってところです。

以上


---------------------
クラスに書き換えたヴァージョン

  class Program
  {
    static void Main()
    {
      var list = new List();
      list.Add(1);
      list.Add(2);
      list.Add(3);

      foreach (int value in list.GetEnumerable())
      {
        Console.WriteLine(value);
      }
    }
  }

  public class List // : IEnumerable
  {
    private ListNode _first;
    private ListNode _last;

    public void Add(object value)
    {
      dynamic node = new ListNode {Value = value};
      if (_first == null)
        _first = _last = node;
      else
        _last = _last.Next = node;
    }

    public IEnumerable GetEnumerable()
    {
      for (ListNode currentNode = _first; currentNode != null; currentNode = currentNode.Next)
      {
        yield return currentNode.Value;
      }
    }

    class ListNode
    {
      public object Value { get; set; }
      public ListNode Next { get; set; }
    }

    //public IEnumerator GetEnumerator()
    //{
    //  return GetEnumerable().GetEnumerator();
    //}
  }

【C#4.0】クラスを定義せず実行時にLinkedListなオブジェクトを作る。

  • 2011.05.11 Wednesday
  • 21:41
JUGEMテーマ:コンピュータ

昨日に引き続きDynamicObjectを利用して、遊んでみました。
実行時にdynamicを利用してあたかもLinkedListオブジェクトのような
振る舞いを示すオブジェクトを生成するコードを書いてみました。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;

namespace DynamicDemo20110511_001
{
  class Program
  {
    static void Main(string[] args)
    {
      dynamic linkedList = CreateLinkedList();
      AddLinkedListNode(linkedList, 1);
      AddLinkedListNode(linkedList, 2);
      AddLinkedListNode(linkedList, 3);
      AddLinkedListNode(linkedList, 4);

      Console.WriteLine("前方から");
      foreach (dynamic value in GetValuesForward(linkedList))
      {
        Console.WriteLine(value);
      }

      Console.WriteLine("後方から");
      foreach (dynamic value in GetValuesBack(linkedList))
      {
        Console.WriteLine(value);
      }
    }

    static IEnumerable GetValuesForward(dynamic linkedList)
    {
      for (dynamic current = linkedList.First; current != null; current = current.Next)
      {
        yield return current.Value;
      }
    }

    static IEnumerable GetValuesBack(dynamic linkedList)
    {
      for (dynamic current = linkedList.Last; current != null; current = current.Previous)
      {
        yield return current.Value;
      }
    }

    static dynamic CreateLinkedList()
    {
      dynamic linkedList = NamedDynamicObject.Create();
      linkedList.First = null;
      linkedList.Last = null;
      return linkedList;
    }

    static void AddLinkedListNode(dynamic linkedList, dynamic value)
    {
      dynamic newItem = NamedDynamicObject.Create();
      newItem.Value = value;
      newItem.Previous = linkedList.Last;
      newItem.Next = null;

      if (linkedList.Last != null)
        linkedList.Last.Next = newItem;

      linkedList.Last = newItem;
      
      if (linkedList.First == null)
        linkedList.First = linkedList.Last;
    }
  }

  public class NamedDynamicObject : DynamicObject
  {
    public static dynamic Create()
    {
      return new NamedDynamicObject();
    }

    protected NamedDynamicObject()
    {
      _setting = new Dictionary<string, object>();
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      return _setting.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
      _setting[binder.Name] = value;
      return true;
    }

    private readonly Dictionary<string, object> _setting;
  }
}

LinkListクラスとLinkedListNodeクラスの実装をどうやって実装すればいいか
クラスを定義せずに必要となるであろう処理のみを記述することできあがりました。
なかなかおもしろかったです(面白いだけです)

【C#4.0】ラッパークラスDynamicObjectで遊んでみる。

  • 2011.05.10 Tuesday
  • 23:01

Source and Project

MSDNライブラリーのDynamicObjectの紹介でラッパークラスの実装が紹介されていたので
それを参考に自分で実装してみた。

動的にプロパティを定義できるオブジェクトを生成するクラス。

  public class NamedDynamicObject : DynamicObject
  {
    public static dynamic Create()
    {
      return new NamedDynamicObject();
    }

    protected NamedDynamicObject()
    {
      _setting = new Dictionary<string, object>();
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
      return _setting.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
      _setting[binder.Name] = value;
      return true;
    }

    private readonly Dictionary<string, object> _setting;
  }

このオブジェクトをdynamicで受けることにより
クラスで定義されていないメンバーへアクセスしているようなコードが記述出来る。

使用例は

  class Program
  {
    static void Main(string[] args)
    {
      dynamic top = NamedDynamicObject.Create();
      top.Value = 1;
      top.Next = NamedDynamicObject.Create();
      top.Next.Value = 2;
      top.Next.Next = NamedDynamicObject.Create();
      top.Next.Next.Value = 3;
      top.Next.Next.Next = top;

      top.Print = new Action<dynamic>(PrintList);
      top.Print(top);
    }

    static void PrintList(dynamic top)
    {
      dynamic current = top;
      for (int i = 0; i < 10; i++)
      {
        Console.WriteLine(current.Value);
        current = current.Next;
      }
    }
  }

特に意味のあるコードではないが、NamedDynamicObjectクラスで定義されていないメンバーに
アクセスして値やインスタンスが設定されている。
デリゲートを利用して、メンバー経由でデリゲートを実行してみた。
(TryInvokeMemberメソッドを利用すればメソッドのオーバーロードも実現できそう)

オブジェクトにたいして全て外部から定義をしてオブジェクトを操作する。
なんだかともて不思議な感じです。

Source and Project

C# 4.0 In a Nutshell

  • 2010.04.22 Thursday
  • 00:37
JUGEMテーマ:コンピュータ


C# 4.0 In a Nutshell

C$3.0版がものすごく良かったので、C#4.0版も良いに決ってます。
シンプルだけどものすごく役に立つ本。

既に発売されていたんですね。気がつかなかった。

【C#4.0】Visual Studio 2010 and .NET Framework 4.0 Training Kit - November Previewが公開。

  • 2008.11.14 Friday
  • 00:54
Visual Studio 2010 and .NET Framework 4.0 Training Kit - November Previewが公開されています。

引用元
もり ひろゆきの日々是勉強
http://blogs.wankuma.com/hirom/archive/2008/11/13/161272.aspx



これはうれしいトレーニングキットになりそうです。
出来れば日本語がほしいところです!(←力強く「!」をおしちゃいました)

Visual Studio 2010 and .NET Framework 4.0 Training Kit - November Preview

【.NET】Visual Studio 2010 and .NET Framework 4.0 CTP フィードバック

  • 2008.11.05 Wednesday
  • 22:56
https://connect.microsoft.com/VisualStudioJapan/content/content.aspx?ContentID=10212

Visual Studio 2010 と .NET Framework 4.0 の Community Technology Preview (CTP) フィードバック ページが開設されましたね〜。
日本語の「Visual Studio 2010 CTP ウォークスルー (評価ガイド) 」がおいてあったりでウハウハです。






calendar

S M T W T F S
     12
3456789
10111213141516
17181920212223
24252627282930
31      
<< March 2024 >>

あわせて読みたい

あわせて読みたいブログパーツ

selected entries

categories

archives

recent comment

  • 【WPF】DataGridに編集可能なComboBoxを表示するには?
    art55 (07/16)
  • 【WPF】DataGridに編集可能なComboBoxを表示するには?
    arisa (07/16)
  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    art55 (05/22)
  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    分解大好き (05/18)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/04)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    Gen (02/04)
  • 【キーボード】RealForce が壊れて帰ってきた。
    art55 (04/29)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/23)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    かるあ (02/22)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    art55 (01/16)

recent trackback

recommend

recommend

recommend

C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION)
C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION) (JUGEMレビュー »)
Sasha Goldshtein,Dima Zurbalev,Ido Flatow,サシャ・ゴルドシュタイン,ディマ・ズルバレフ,イド・フラトー

recommend

ろんりと集合
ろんりと集合 (JUGEMレビュー »)
中内 伸光
とてもわかりやすいです。

recommend

recommend

シャノン・ノイマン・ディジタル世界
シャノン・ノイマン・ディジタル世界 (JUGEMレビュー »)
市川 忠男
4章がリレーショナルデータベースな内容になってます。ページ数があまりありませんが、ポイントがものすごく的確にまとまっていて、感動します。

recommend

recommend

東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS
東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS (JUGEMレビュー »)

テンキーレス、静音のRealForce91UBK-S。スコスコ感がたまらなく気持ちいいです。家と会社で2台持ってます。

recommend

recommend

プログラミング.NET Framework 第4版 (プログラミングシリーズ)
プログラミング.NET Framework 第4版 (プログラミングシリーズ) (JUGEMレビュー »)
Jeffrey Richter
発売予定美 2013年10月10日。.NET Frameworkとお付き合いする人のバイブルですね。

recommend

recommend

キャット・シッターの君に。
キャット・シッターの君に。 (JUGEMレビュー »)
喜多嶋 隆
私のイラストレータデビュー本です。

recommend

Essential .NET ― 共通言語ランタイムの本質
Essential .NET ― 共通言語ランタイムの本質 (JUGEMレビュー »)
ドン・ボックス,クリス・セルズ,Don Box,Chris Sells,吉松 史彰

links

profile

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM