web-dev-qa-db-ja.com

For Each(VB.NET)の最後のループをどのように見つけますか?

VB.NETのForEachステートメントの最後のループに入っているかどうかを確認するにはどうすればよいですか?

24
RichC

一般に、For Eachを実行できるコレクションは、 IEnumerator インターフェイスを実装します。このインターフェースには、MoveNextResetの2つのメソッドと、Currentの1つのプロパティしかありません。

基本的に、コレクションでFor Eachを使用すると、コレクションはMoveNext関数を呼び出し、返された値を読み取ります。返される値がTrueの場合、コレクションに有効な要素があり、要素はCurrentプロパティを介して返されます。コレクションにこれ以上要素がない場合、MoveNext関数はFalseを返し、反復は終了します。

上記の説明から、For Eachがコレクション内の現在の位置を追跡していないことは明らかであるため、質問に対する答えは短いですいいえ

ただし、コレクションの最後の要素にいるのかどうかを知りたい場合は、次のコードを試すことができます。現在のアイテムが最後のアイテムであるかどうかを(LINQを使用して)チェックします。

For Each item in Collection
    If item Is Collection.Last Then
        'do something with your last item'
    End If
Next
54
Alex Essilfie

ForEachの代わりにForループを使用する方がおそらく簡単でしょう。ただし、同様に、ForEachループ内にカウンターを保持し、それがyourCollection.Count - 1に等しいかどうかを確認すると、最後の反復になります。

13
Strelok

Foreachを使用すると、手遅れになるまで(つまり、ループから外れるまで)これを知ることはできません。

IEnumerableインターフェイスしかないものを使用していると想定していることに注意してください。リストや配列などがある場合は、ここで.Countなどを使用する他の回答に従って、アイテムの数を確認してください。これにより、コレクション内のどこにいるかを追跡できます。

ただし、IEnumerable/IEnumeratorだけでは、foreachを使用する場合、それ以上あるかどうかを確実に知る方法はありません。

これを知る必要がある場合は、IEnumerableを自分で使用してください。これはforeachが行うことです。

以下のソリューションはC#用ですが、VB.NETに簡単に変換できるはずです。

List<Int32> nums = new List<Int32>();
nums.Add(1);
nums.Add(2);
nums.Add(3);

IEnumerator<Int32> enumerator = nums.GetEnumerator();
if (enumerator.MoveNext())
{
    // at least one value available
    while (true)
    {
        // make a copy of it
        Int32 current = enumerator.Current;

        // determine if it was the last value
        // if not, enumerator.Current is now the next value
        if (enumerator.MoveNext())
        {
            Console.Out.WriteLine("not last: " + current);
        }
        else
        {
            Console.Out.WriteLine("last: " + current);
            break;
        }
    }
}
enumerator.Dispose();

これは印刷されます:

not last: 1
not last: 2
last: 3

秘訣は、現在の値のコピーを取り、列挙子に次の値に移動するように依頼することです。それが失敗した場合、あなたが作成したコピーは確かに最後の値でした、そうでなければもっとあります。

簡単な答え:できません

長い答え:For Eachステートメントのセマンティクスには、最初、最後、または特定の反復を実行しているかどうかを識別することを可能にするものは何もありません。

ForEachはIEnumerableおよびIEnumerable <>インターフェイスに組み込まれており、動作は呼び出している実装によって異なります。紛らわしいですが、毎回異なる順序で要素を返すことを繰り返しているコレクションには有効です。幸い、List <>はこれを行いません。

特定の反復が最後であることを本当に知る必要がある場合は、最後の要素を(事前に)識別し、その要素に遭遇したときに別のアクションを実行できます。

より簡単なのは、最初の反復を(たとえば、ブール値を介して)検出してから、別のことを行うことです。

例(C#ですが、VBも同様です):

StringBuilder result = new StringBuilder();
bool firstTime = true;
foreach(string s in names)
{
    if (!firstTime)
    {
        result.Append(", ");
    }

    result.Append(s);
    firstTime = false;
}
2
Bevan

私はこの投稿に戻ってくるので、座ってこの問題について考えることにし、これを思いついた:

_    For Each obj In myCollection
        Console.WriteLine("current object: {0}", obj.ToString)

        If Object.ReferenceEquals(obj, myCollection.Last()) Then
            Console.WriteLine("current object is the last object")
        End If
    Next
_

必要に応じて、_If...Then...End If_ステートメントを1行に減らすこともできます。すべての反復で.Last()を呼び出すことがパフォーマンスに大きな影響を与えるかどうかはわかりませんが、それが夜に目を覚まし続けるのであれば、ループ外の変数にいつでも割り当てることができます。

1
Steven Liekens

要素がコンテナの最後の要素であるかどうかを確認します。

なぜあなたはそれをしたいのですか?
ループの後に命令を配置するだけで済みます。 (最後の要素で実行すること)

1
Tamara Wijsman

ForEachの代わりにForループを使用する方が簡単ですが、次のようなことができます。

If item.Equals(itemCollection(itemCollection.Count)) Then
    ...
End If

forEachループの内部...オブジェクトがEqualsメソッドを適切にオーバーライドしたと仮定します。

これは、Forループを使用したり、別の変数で現在のインデックスを追跡したりするよりも、おそらくはるかに多くのリソースを消費します。

これが正しい構文かどうかはわかりません。VBを使用してから久しぶりです。

1
Rex Morgan

標準の「ForEach」ループを使用することはできません。 「forEach」ループの目的は、基になるコレクションの代わりにデータに集中できるようにすることです。

1
JaredPar

このコードサンプルが役立つかもしれません

For Each item in Collection
  If ReferenceEquals(Collection.Item(Collection.Count - 1), item) Then
    'do something with your last item'
  End If
Next
1
sh0hei

回避策はほとんどありません。CheckBoxListを使用しているとします。

次に、このコードサンプルが役立つ可能性があります。

Dim count As Integer = 0
Dim totalListCount As Integer = CheckBoxList.Items.Count()
For Each li In CheckBoxList.Items
         count += 1
           // This is the Last Item
      If count = totalListCount THEN
          // DO Somthing.....
      END IF
NEXT     
0
panky sharma

IEnumerableに関連付けられている場合。 foreachループ内にいる必要がありますか?そうでない場合は、foreachループの直前に変数を宣言できます。ループ中に設定します。次に、ループの後に使用します(nullでない場合)

0
Greg Dean

これは私が政治的に正しいかどうかわからない簡単なことですが、それは機能します

for each item in listOfThings
   if(item = listOfThings.last)then 
       'you found the last loop
   end if
next 
0
bobby shneider