C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: yield returnに関して


(過去ログ 43 を表示中)

[トピック内 3 記事 (1 - 3 表示)]  << 0 >>

■22651 / inTopicNo.1)  yield returnに関して
  
□投稿者/ foo (3回)-(2008/07/29(Tue) 11:49:06)

分類:[C#] 

たびたびお世話になっています。
前回、Rubyのeachに関してスレッドを立てた者です。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=22630
今回もその続きです。

おかげさまで疑問が解決して、以下のようにC#に翻訳しました。

class PowerSetGenerator
{
 int[] _set;

 public PowerSetGenerator(int[] set)
 {
  _set = set;
 }

 public List<List<int>> GetPowerSet()
 {
  List<List<int>> ret = new List<List<int>>();

  int nElem = (int)Math.Pow(2, _set.Length);
  for (int i = 0; i < nElem; i++)
  {
   int n = i;
   List<int> a = new List<int>();

   // 前回質問したところ
   foreach (int m in _set)
   {
    if (1 == (n & 1)) a.Add(m);
    n >>= 1;
   }
   ret.Add(a);
  }
  return ret;
 }
}

集合がn個の要素からなるとき、その集合から作るべき集合の要素は2^n個になります。
なので、GetPowerSetを実行すると戻り値が物凄い量のメモリを消費してしまいますね。(intなので高が知れてますが...

そんなときに知ったのがyield return。
以下のように書き換えれば、べき集合を一気に作ってしまわずに小出しにできるのではと思ったのですが、そもそも使用方法は合っているのでしょうか。
私が期待しているような動きになっているのでしょうか。
(と言っても、「私が期待している動き」というものを説明できていませんが。)
class PowerSetGenerator
{
 int[] _set;

 public PowerSetGenerator(int[] set)
 {
  _set = set;
 }

 public IEnumerable<List<int>> GetPowerSet()
 {
  int nElem = (int)Math.Pow(2, _set.Length);
  for (int i = 0; i < nElem; i++)
  {
   int n = i;
   List<int> a = new List<int>();

   foreach (int m in _set)
   {
    if (1 == (n & 1)) a.Add(m);
    n >>= 1;
   }
   yield return a;
  }
 }
}

実行したら一応どちらも同じになりました。
引用返信 編集キー/
■22652 / inTopicNo.2)  Re[1]: yield returnに関して
□投稿者/ れい (722回)-(2008/07/29(Tue) 12:37:47)
No22651 (foo さん) に返信
> 私が期待しているような動きになっているのでしょうか。

なってると思いますが。

元のコードだとべき集合を生成してますが
yieldの場合はべき集合を生成しつつ列挙してるという話なので、
うまく使い分けるとよいかと。

列挙の途中で元の集合が変わっちゃったときにどうするかとか、
考えないといけないですね

もとの集合の要素の個数から
べき集合の個数は求められるし、
べき集合の要素にインデックスをつけ、
インデックスからべき集合の要素を作成するのも簡単なので
「ジェネリックなべき集合コレクションクラス」を作成して、
インデクサ内部でその場生成するとよいかと思いますが。

引用返信 編集キー/
■22784 / inTopicNo.3)  Re[2]: yield returnに関して
□投稿者/ foo (4回)-(2008/08/01(Fri) 10:30:41)
れいさん、レスとアドバイスありがとうございました。
遅くなってすみません。

> 列挙の途中で元の集合が変わっちゃったときにどうするかとか、
> 考えないといけないですね
元の集合は不変という前提ですので、この点は特に考える必要がなさそうです。

> もとの集合の要素の個数からべき集合の個数は求められるし、
> べき集合の要素にインデックスをつけ、
> インデックスからべき集合の要素を作成するのも簡単なので
> 「ジェネリックなべき集合コレクションクラス」を作成して、
> インデクサ内部でその場生成するとよいかと思いますが。
なるほど。そういう手段もありますね。
ってか、yieldよりもこっちの方が分かりやすいかも...。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -