次のコードスニペットがあるとします。
var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
if(data[i]=="One"){
data.RemoveAt(i);
}
}
次のコードは例外をスローします。
私の質問は、この例外を回避し、ループ中に要素を削除する最良の方法は何ですか?
要素を削除する必要がある場合は、リストの最後から要素を削除できるように、逆方向に反復する必要があります。
var data=new List<string>(){"One","Two","Three"};
for(int i=data.Count - 1; i > -1; i--)
{
if(data[i]=="One")
{
data.RemoveAt(i);
}
}
ただし、LINQを使用してこれを行うより効率的な方法があります(他の回答で示されているように)。
List<T>.RemoveAll
これを処理するには:
data.RemoveAll(elem => elem == "One");
私はたまたまforeach
と.ToArray()
を使用してこのための簡単なソリューションに出くわしました
var data=new List<string>(){"One","Two","Three"};
foreach ( var d in data.ToArray()){
if(d =="One"){
data.Remove(d);
}
}
次のような前方移動ループを使用することもできます。
_var data = new List<string>() { "One", "Two", "Three", "One", "One", "Four" };
for (int i = 0; i < data.Count; i++)
{
if (data[i] == "One")
{
data.RemoveAt(i--);
}
}
_
この行data.RemoveAt(i--);
は、リストから項目が削除された場合に、ループの終わりで反復変数の増分の効果を停止します。
現在の反復値でインデックスからアイテムを削除し、アイテムを削除した後、イテレータは現在の値よりも1つ少ない値に設定されます。ループの終わりに、ループ本体の増分はそれを次の有効なインデックスに移動します。
ここに働く dotfiddle
(IMO、これらは理解しやすいので、このような状況では個人的に逆ループを使用していることに注意してください、ここでのこの答えは、それを達成する別の方法を表示するためのものです)。
ChrisFの逆反復法を試して、アイテムを削除できます。
また、単に次のことができます。
List.Remove("One");
または:
List.RemoveAll(i => i == "One"); // removes all instances
そして、それで終わりです。コレクションを繰り返して単一のアイテムを削除しても意味がありません。
イテレータ変数を単純にデクリメントしてみませんか?
var data=new List<string>(){"One","Two","Three"};
for(int i=0 ; i<data.Count ; i++){
if(data[i]=="One"){
data.RemoveAt(i);
i--; // <<<<<<<<<<<
}
}
ここに汚いトリックがあり、その批評はどうなるのだろうか?
var data=new List<string>(){"One","Two","Three"};
foreach (string itm in (data.ToArray()))
{
if string.Compare(name, "one", true) == 0) data.Remove(name);
}
以下の一般的な解決策は、リストのコピーを作成し、負のインデックスを処理します。
foreach (void item_loopVariable in MyList.ToList) {
item = item_loopVariable;
}
var data = new List<string>() { "One", "Two", "Three" };
data.RemoveAll(p=>p=="One");
var data=new List<string>(){"One","Two","Three"};
for(int i=0; i<data.Count; ){
if(data[i]=="One") data.RemoveAt(i);
else ++i;
}
Stackクラスを使用できます
Stack<string> myStack = new Stack<string>();
foreach (var item in Enumerable.Range(1,1001))
myStack.Push("Str " + item.ToString());
while (myStack.Any())
Console.WriteLine("Now {0} items in Stack, removed item is {1}",myStack.Count,myStack.Pop());
Console.ReadKey();
リストから複数のアイテムを削除する必要がありました。そのため、リストカウントを再初期化しました。他のより良いオプションはありますか?
for (int i = dtList.Count - 1; dtList.Count > 0; )
{
DateTime tempDate = dtList[i].Item1.Date;
var selectDates = dtList.FindAll(x => x.Item1.Date == tempDate.Date);
selectDates.Sort((a, b) => a.Item1.CompareTo(b.Item1));
dtFilteredList.Add(Tuple.Create(selectDates[0].Item1, selectDates[0].Item2));
dtList.RemoveAll(x => x.Item1.Date == tempDate.Date);
i = dtList.Count - 1;
}