7

私がこのクエリを持っているとしましょう:

  int[] Numbers= new int[5]{5,2,3,4,5};

  var query =  from a in Numbers
      where a== Numbers.Max (n => n) //notice MAX  he should also get his value somehow
      select a;

foreach (var element in query)
  Console.WriteLine (element);
  • 実行時に何回列挙されNumbersます か?foreach

  • どうすればテストできますか(つまり、反復回数を教えてくれるコードを書くことです)

4

7 に答える 7

3

6回繰り返されます。の場合は1回、。Whereの場合は要素ごとに1回Max

これを示すコード:

private static int count = 0;
public static IEnumerable<int> Regurgitate(IEnumerable<int> source)
{
    count++;
    Console.WriteLine("Iterated sequence {0} times", count);
    foreach (int i in source)
        yield return i;
}

int[] Numbers = new int[5] { 5, 2, 3, 4, 5 };

IEnumerable<int> sequence = Regurgitate(Numbers);

var query = from a in sequence
            where a == sequence.Max(n => n)
            select a;

「6回の繰り返しシーケンス」を出力します。

これを使用して他のケースを試すことを計画している場合は、より柔軟な、より汎用的なラッパーを作成できます。

public class EnumerableWrapper<T> : IEnumerable<T>
{
    private IEnumerable<T> source;
    public EnumerableWrapper(IEnumerable<T> source)
    {
        this.source = source;
    }

    public int IterationsStarted { get; private set; }
    public int NumMoveNexts { get; private set; }
    public int IterationsFinished { get; private set; }

    public IEnumerator<T> GetEnumerator()
    {
        IterationsStarted++;

        foreach (T item in source)
        {
            NumMoveNexts++;
            yield return item;
        }

        IterationsFinished++;
    }

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

    public override string ToString()
    {
        return string.Format(
@"Iterations Started: {0}
Iterations Finished: {1}
Number of move next calls: {2}"
, IterationsStarted, IterationsFinished, NumMoveNexts);

    }
}

これには、他の機能に比べていくつかの利点があります。

  1. 開始された反復回数、完了した反復回数、およびすべてのシーケンスが増分された合計回数の両方が記録されます。
  2. さまざまなインスタンスを作成して、さまざまな基になるシーケンスをラップできるため、静的変数を使用する場合に1つだけではなく、プログラムごとに複数のシーケンスを検査できます。
于 2012-12-04T15:35:44.933 に答える
3

カウントを確認する方法は次のとおりです

void Main()
{
    var Numbers= new int[5]{5,2,3,4,5}.Select(n=>
    {
       Console.Write(n);
       return n;
    });

    var query =  from a in Numbers
                 where a== Numbers.Max (n => n)
                 select a;

    foreach (var element in query)
    {
          var v = element;
    }
}

ここに出力があります

5 5 2 3 4 5 2 5 2 3 4 5 3 5 2 3 4 5 4 5 2 3 4 5 5 5 2 3 4 5  
于 2012-12-04T15:35:25.637 に答える
3

コレクションが列挙された回数のクイックカウントを見積もる方法は次のとおりです。コレクションをでラップし、次のようCountedEnum<T>にそれぞれのカウンターをインクリメントします。yield return

static int counter = 0;

public static IEnumerable<T> CountedEnum<T>(IEnumerable<T> ee) {
    foreach (var e in ee) {
        counter++;
        yield return e;
    }
}

次に、配列宣言をこれに変更します。

var Numbers= CountedEnum(new int[5]{5,2,3,4,5});

クエリを実行し、を出力しますcounter。クエリの場合、コードは30(ideoneへのリンク)を出力します。これは、5つのアイテムのコレクションが6回列挙されたことを意味します。

于 2012-12-04T15:40:51.630 に答える
1

反復回数はに等しくなければなりませんquery.Count()

したがって、最初のクエリの結果の要素の数になります。

他に質問がある場合は、明確にしてください。

編集

明確化後:

提供されたコードで反復の総数を検索している場合は、反復があり7ます(この具体的なケースの場合)。

var query =  from a in Numbers
      where a== Numbers.Max (n => n) //5 iterations to find MAX among 5 elements
      select a;

foreach (var element in query)
  Console.WriteLine (element); //2 iterations over resulting collection(in this question)
于 2012-12-04T15:33:27.583 に答える
1

foreachを実行すると、Numbersは何回列挙されますか

大まかに言えば、あなたのコードは道徳的に次のものと同等です:

foreach(int a in Numbers)
{
   // 1. I've gotten rid of the unnecessary identity lambda. 
   // 2. Note that Max works by enumerating the entire source.
   var max = Numbers.Max();

   if(a == max)
     Console.WriteLine(a);
}

したがって、次の時間を列挙します。

  1. 外側のループのシーケンスの1つの列挙(1)。
  2. 各メンバーのシーケンスの1つの列挙(Count)。

したがって、合計で時間を列挙Count + 1します。

ローカルを導入してループの外にクエリ2を上げることで、これを下げることができます。Max

どうすればテストできますか(つまり、反復回数を教えてくれるコードを書くことです)

これは、生の配列では簡単ではありません。ただし、独自の列挙可能な実装(おそらく配列をラップする)を記述して、GetEnumeratorメソッドにインストルメンテーションを追加することもできます。または、さらに深く掘り下げたい場合は、全体を調べて、インストルメンテーションをオンにしたカスタム列挙子を作成しMoveNextますCurrent

于 2012-12-04T15:45:50.353 に答える
1

公共の財産を介してカウントすることも6をもたらします。

private static int ncount = 0;
private int[] numbers= new int[5]{5,2,3,4,5};
public int[] Numbers 
{ 
    get
    {
        ncount++;
        Debug.WriteLine("Numbers Get " + ncount.ToString());  
        return numbers;
    }
}

これにより、カウントが2になります。
理にかなっていますが、私はそれについて考えていなかったでしょう。

int nmax = Numbers.Max(n => n);
var query = from a in Numbers
    where a == nmax //notice MAX  he should also get his value somehow
    //where a == Numbers.Max(n => n) //notice MAX  he should also get his value somehow
select a;
于 2012-12-04T16:13:05.900 に答える
0

6回繰り返されます。の場合は1回、。Whereの場合は要素ごとに1回Max

foreachループの外側で変数を定義して初期化し、ループの内側countでカウント変数をインクリメントしてcount++、列挙の回数を取得します。

于 2012-12-04T16:38:00.553 に答える