次のように結果リストにリストが保存されています。
var resultlist = results.ToList();
これは次のようになります。
ID FirstName LastName
-- --------- --------
1 Bill Smith
2 John Wilson
3 Doug Berg
リストからID2を削除するにはどうすればよいですか?
List<T>
には 2 つの方法があります。
アイテムのインデックスがわかっている場合は、 RemoveAt(int index)を使用できます。例えば:
resultlist.RemoveAt(1);
または、 Remove(T item)を使用できます:
var itemToRemove = resultlist.Single(r => r.Id == 2);
resultList.Remove(itemToRemove);
アイテムが実際に存在するかどうかわからない場合は、SingleOrDefaultを使用できます。アイテムがない場合SingleOrDefault
は返されます (アイテムが見つからない場合は例外がスローされます)。重複する値 (同じ を持つ 2 つの項目) がある場合、両方がスローされます。null
Single
id
var itemToRemove = resultlist.SingleOrDefault(r => r.Id == 2);
if (itemToRemove != null)
resultList.Remove(itemToRemove);
簡単な答え:
削除 (リストからresults
)
results.RemoveAll(r => r.ID == 2);
ID 2のアイテムをresults
(インプレースで)削除します。
フィルター (元のリストから削除せずにresults
):
var filtered = result.Where(f => f.ID != 2);
ID 2のアイテムを除くすべてのアイテムを返します
詳細な回答:
.RemoveAll()
削除したいアイテム ID のリストを持つことができるので、非常に柔軟だと思います。次の例を参考にしてください。
あなたが持っている場合:
class myClass {
public int ID; public string FirstName; public string LastName;
}
次のようにいくつかの値を割り当てresults
ます。
var results = new List<myClass> {
new myClass { ID=1, FirstName="Bill", LastName="Smith" }, // results[0]
new myClass { ID=2, FirstName="John", LastName="Wilson" }, // results[1]
new myClass { ID=3, FirstName="Doug", LastName="Berg" }, // results[2]
new myClass { ID=4, FirstName="Bill", LastName="Wilson" } // results[3]
};
次に、削除する ID のリストを定義できます。
var removeList = new List<int>() { 2, 3 };
そして、これを使用してそれらを削除するだけです:
results.RemoveAll(r => removeList.Any(a => a==r.ID));
で指定されているように、アイテム 2 と 3 を削除し、アイテム 1 と 4 を保持しますremoveList
。これはその場で行われるため、追加の割り当ては必要ありません。
もちろん、次のような単一のアイテムにも使用できます。
results.RemoveAll(r => r.ID==4);
この例では、ID 4 の Bill が削除されます。
最後に言及することは、リストにはインデクサーがあることです。つまり、動的配列のようにアクセスすることもできます。つまりresults[3]
、結果リストの 4 番目の要素が返されます (最初の要素のインデックスは 0、2 番目の要素のインデックスは1など)。
したがって、最初の名前が結果リストの 4 番目の要素と同じであるすべてのエントリを削除する場合は、次のように簡単に実行できます。
results.RemoveAll(r => results[3].FirstName == r.FirstName);
その後、John と Doug だけがリストに残り、Bill は削除されることに注意してください (例の最初と最後の要素)。重要なのは、リストが自動的に縮小されるため、残りの要素は 2 つだけであるため、この例で RemoveAll を実行した後に許可される最大のインデックスは 1
(つまりresults.Count() - 1
) です。
トリビア: この知識を使用して、ローカル関数を作成できます。
void myRemove() { var last = results.Count() - 1;
results.RemoveAll(r => results[last].FirstName == r.FirstName); }
この関数を 2 回呼び出すとどうなると思いますか? お気に入り
myRemove(); myRemove();
最初の呼び出しで Bill が最初と最後の位置から削除され、2 回目の呼び出しで Doug が削除され、John Wilson だけがリストに残ります。
注: C# バージョン 8以降では、 and results[^1]
の代わりに次のように書くこともできます。var last = results.Count() - 1;
results[last]
void myRemove() => results.RemoveAll(r => results[^1].FirstName == r.FirstName);
したがって、ローカル変数はもう必要ありlast
ません ( indexs and rangesを参照してください)。さらに、これはワンライナーであるため、中括弧は必要なく、=>
代わりに使用できます。C# のすべての新機能の一覧については、こちらを参照してください。
DotNetFiddle:デモを実行する
resultList = results.Where(x=>x.Id != 2).ToList();
実装が簡単で、「どこにない」条件のクエリを少し読みやすくすることができる、私が気に入っている小さなLinqヘルパーがあります。
public static IEnumerable<T> ExceptWhere<T>(this IEnumerable<T> source, Predicate<T> predicate)
{
return source.Where(x=>!predicate(x));
}
//usage in above situation
resultList = results.ExceptWhere(x=>x.Id == 2).ToList();
より単純化:
resultList.Remove(resultList.Single(x => x.Id == 2));
新しい var オブジェクトを作成する必要はありません。
リストの種類は指定しませんが、一般的な List はRemoveAt(index)
メソッドまたはメソッドのいずれかを使用できますRemove(obj)
。
// Remove(obj)
var item = resultList.Single(x => x.Id == 2);
resultList.Remove(item);
// RemoveAt(index)
resultList.RemoveAt(1);
別のアプローチがあります。と を使用List.FindIndex
しList.RemoveAt
ます。
私はおそらくKeithSによって提示されたソリューション (単純なWhere
/のみToList
) を使用するでしょうが、このアプローチは元のリスト オブジェクトを変更するという点で異なります。これは、期待に応じて、良い (または悪い) "機能" になる可能性があります。
いずれにせよ、FindIndex
(ガードと結合された) はRemoveAt
、ID にギャップがある場合や順序が間違っている場合などに が正しいことを保証し、 RemoveAt
(vs ) を使用すると、リスト内での2 回目のO(n) 検索Remove
が回避されます。
LINQPadスニペットは次のとおりです。
var list = new List<int> { 1, 3, 2 };
var index = list.FindIndex(i => i == 2); // like Where/Single
if (index >= 0) { // ensure item found
list.RemoveAt(index);
}
list.Dump(); // results -> 1, 3
ハッピーコーディング。
...またはresultlist.RemoveAt(1)
インデックスを正確に知っている場合。