web-dev-qa-db-ja.com

LINQまたはLambdaを使用してリストからインスタンスを削除しますか?

すべてのデータをリストとしてcache(objects)に取得する段階になりました。次に、リストからいくつかのインスタンスを削除する必要があります。

通常、私はこのように削除します:

_List<T> list;
List<T2> toBeRemovedItems;
// populate two lists
foreach(T2 item in toBeRemovedItems)
{
    list.Remove(delegate(T one) { 
        // build a condition based on item
        // return true or false
    });
}
_

具体的には、動的クラス(正式に定義されたクラスではない)のtoBeRemvoedItemsリストを実際に作成または設定します。たとえば、TクラスはMyClassのようなもので、削除するためのコードは次のとおりです。

_class MyClass<C> {
    public string Value1 { get; set; }
    public int Value2 { get; set; }
    public C ObjectC { get; set; }
}
....
List<MyClass<C>> list;
// populate list
// populate toBeRemovedItems. Here is an example of hard-coded codes:
var toBeRemovedLItems = new[] {
    new { Value1="a", Value2 = 1},
    new { Value2="x", Value2 = 10},
    ...
};
// toBeRemovedItems may be the result of Select from a collection
foreach(var item in toBeRemovedLItems)
{
    list.Remove(delegate(MyClass one) {
        return one.Value1 = item.Value1 && one.Value2 < item.Value2;
    });
}
_

MSDNのIEnumerableインターフェイスでRemove()メソッドを検索しようとしましたが、Remove()のメソッドが見つかりません(IEnumerable列挙にのみ使用されます)。 Listクラスには、いくつかのオーバーロードされたRemove(...)メソッドがあります。 LINQまたはLambda式を使用してリストから項目を削除する別の方法があるかどうかはわかりませんか?

ちなみに、リストに対して項目を移動するのと同じように、リストに対してクエリを実行してサブセットを取得する方法、またはWhere条件を含む新しいIEnumerableリストを取得する方法について考えました。ただし、キャッシュリストから項目を削除することを好み、クラスのリストプロパティを新しいリスト(プライベートセットなど)にリセットできない場合があります。

28
David.Chu.ca

メソッドRemoveAllを使用できます。

MyClass one; //initialize MyClass
list.RemoveAll(item => one.Value1 == item.Value1 && one.Value2 < item.Value2);
41
Francis B.

LINQのWhereメソッドを使用して、リストに含まれてはならない値を除外できます。結果は、要素が削除されたIEnumerable<T>です。

var res = list.Where(item => !(one.Value1 == item.Value1 && one.Value2 < item.Value2));

これにより、元のList<T>インスタンスは更新されませんが、値が削除された新しいIEnumerable<T>が作成されます。

21
JaredPar

質問が正しければ、2つのリストから一意のセットを作成します。

これには、以下を使用できます

リストlist1;リストlist2;

リストlist3 = list1.Except(list2)

List3には一意のアイテムが含まれます。

5
Bhaskar

Jaredが提案した特定の項目を除外することに同意しますが、Value1joinを使用する方が効率的な方法のようです。

var res = from item1 in list
          join item2 in toBeRemovedList
            on item1.Value1 equals item2.Value1
          where item1.Value2 >= item2.Value2
          select item1;

pdate:読解に失敗したようです-新しいアプローチ:

var removeDict = toBeRemovedList.ToDictionary(i => i.Value1, i => i.Value2);
list.RemoveAll(item => {
    int itemToRemoveValue2;
    if(removeDict.TryGetValue(item.Value1, out itemToRemoveValue2))
        return item.Value2 < itemToRemoveValue2;
    return false;
});

もちろん、削除するリストを辞書として開始できるとなお良いでしょう。結局のところ、Value1でのマッチをより効率的にしようとしているだけです。

4
dahlbyk
foreach(var item in toBeRemovedLItems) {   
   list.RemoveAll(one => one.Value1 == item.Value1 && one.Value2 < item.Value2); 
}

再び遅すぎる。しかたがない。

リストではないコレクション(RemoveAllを公開できない)の場合でも、ワンライナーでアイテムを削除できます。

インラインを置き換えるには、削除する項目のリストを生成し、それを実行して、削除コードを実行します。

var dictionary = new Dictionary<string, string>(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}};
dictionary
    .Where(where_item =>
        ((where_item.Key == "foo") && (where_item.Value == "0"))
        || ((where_item.Key == "boo") && (where_item.Value == "1"))
    )
    .ToList()
    .ForEach(remove_item => {
        dictionary.Remove(remove_item.Key);
    });

コピーで置き換えるには、フィルター処理された列挙型を生成し、新しいコピーを返すだけです。

var dictionary0 = new Dictionary<string, string>(){{"foo", "0"}, {"boo", "1"}, {"goo", "1"}};
var dictionary1 = dictionary0
    .Where(where_item =>
        ((where_item.Key == "foo") && (where_item.Value == "0"))
        || ((where_item.Key == "boo") && (where_item.Value == "1"))
    )
    .ToDictionary(each_item => each_item.Key, each_item => each_item.Value);
1
Alex

多分あなたはこのようなことをやろうとしているのですか?

List<T> firstList;
List<T2> toBeRemovedItems;
List<T> finalList;

foreach(T item in firstList)
{
    toBeRemovedItems = CheckIfWeRemoveThisOne(item.Number, item.Id);
    if (toBeRemovedItems == null && toBeRemovedItems.Count() == 0)
        finalList.Add(item);
}

これは、List<ViewModel>List<Model>の間の重複を取り除くことで問題を解決した方法です。 CheckIfWeRemoveThisOne関数を使用して、item.Numberが他のアイテムに属しているかどうかを、IDを定義特性として使用して確認しました。別のアイテム(重複)が見つかった場合は、元のリスト(List<Model>を取得していて、最初にList<ViewModel>が関数に与えられていました)から削除するのではなく、とにかく、どうすればそれができるのか疑問に思っていました)、私は新しいリストを作成しました-問題がなければ、結果をリストに追加しました。

0
vapcguy