26

外部アプリから返された人物のリストがあり、リストから人を手動で削除するオプションを提供するために、ローカル アプリで除外リストを作成しています。

作成した両方に共通の複合キーがあり、リストを使用してリストから人を効率的に削除する方法を見つけたい

例えば

class Person
{
    prop string compositeKey { get; set; }
}

class Exclusions
{
    prop string compositeKey { get; set; }
}

List<Person> people = GetFromDB;

List<Exclusions> exclusions = GetFromOtherDB;

List<Person> filteredResults = People - exclustions using the composite key as a comparer

LINQ はこれを行う理想的な方法だと思っていましたが、結合、拡張メソッド、yield の使用などを試した後も、まだ問題が発生しています。

これが SQL の場合、not in (?,?,?)クエリを使用します。

4

9 に答える 9

43

次のように使用するExceptメソッドを見てください。

var resultingList = 
    listOfOriginalItems.Except(listOfItemsToLeaveOut, equalityComparer)

リンク先のオーバーロードを使用すると、カスタム IEqualityComparer を指定できます。そうすれば、複合キーに基づいてアイテムがどのように一致するかを指定できます。(ただし、既に Equals をオーバーライドしている場合は、IEqualityComparer は必要ありません。)

編集: 2つの異なるタイプのクラスを使用しているように見えるので、より簡単な別の方法があります。呼び出されたとList<Person>呼び出された と仮定します。personsList<Exclusion>exclusions

var exclusionKeys = 
        exclusions.Select(x => x.compositeKey);
var resultingPersons = 
        persons.Where(x => !exclusionKeys.Contains(x.compositeKey));

つまり、除外からキーのみを選択し、それらのキーを持たないすべての Person オブジェクトを person から選択します。

于 2009-01-06T16:46:08.427 に答える
9

List クラスで FindAll メソッドを使用するだけです。すなわち:

List<Person> filteredResults = 
    people.FindAll(p => return !exclusions.Contains(p));

構文があなたのオブジェクトと正確に一致するかどうかはわかりませんが、これでどこに行くのかわかると思います。

于 2009-01-06T16:43:40.197 に答える
5

この人たちに感謝します。

私はこれを1行にまとめました:

  var results = from p in People 
                where !(from e in exclusions 
                        select e.CompositeKey).Contains(p.CompositeKey) 
                select p;

ありがとうございました。

于 2009-01-08T12:15:43.247 に答える
4
var thisList = new List<string>{ "a", "b", "c" };
var otherList = new List<string> {"a", "b"};

var theOnesThatDontMatch = thisList
        .Where(item=> otherList.All(otherItem=> item != otherItem))
        .ToList();

var theOnesThatDoMatch = thisList
        .Where(item=> otherList.Any(otherItem=> item == otherItem))
        .ToList();

Console.WriteLine("don't match: {0}", string.Join(",", theOnesThatDontMatch));
Console.WriteLine("do match: {0}", string.Join(",", theOnesThatDoMatch));

//Output:
//don't match: c
//do match: a,b

それに応じてリストの型とラムダを調整すると、何でも除外できます。

https://dotnetfiddle.net/6bMCvN

于 2018-05-02T18:43:26.537 に答える
2

「Except」拡張メソッドを使用できます ( http://msdn.microsoft.com/en-us/library/bb337804.aspxを参照) 。

あなたのコードで

var difference = people.Except(exclusions);
于 2009-01-06T16:44:09.960 に答える
1

純粋な MS LINQ でこれを行う方法がわからなかったので、それを行うための独自の拡張メソッドを作成しました。

public static bool In<T>(this T objToCheck, params T[] values)
{
    if (values == null || values.Length == 0) 
    {
        return false; //early out
    }
    else
    {
        foreach (T t in values)
        {
            if (t.Equals(objToCheck))
                return true;   //RETURN found!
        }

        return false; //nothing found
    }
}
于 2009-01-06T16:41:45.240 に答える