0

こんにちは、Linq を使用して「すべて」のエンティティをリストから削除しようとしています。

問題: データベースに特定の証明書を持つユーザーを検索しています。行ごとにそれらを返すということです....しかし、私が確認する必要があるのは、ユーザーが必要なすべての証明書を保持しているかどうかです。これは、int 配列に対してチェックする必要があります。

これは私の配列です: [3,5,16]、今、リストからこれらの 3 つすべてを持っていないすべてのユーザーを削除したいと思います。コード内の配列の名前は必須です!

返されるリストアイテムは次のようになります

listitem.CertificateValue
listitem.Uid
listitem.NameOfPerson

したがって、基本的にこの例では、Peter はリストに3 つの行を持っています。この場合、リストにとどまるために必要なすべての行です。ただし、Philip には 2 つの行しかないため、合計検索基準を満たしていないため、これらは両方とも削除する必要があります。

また、copyOfMandatory は、元のコレクションを台無しにして期待を引き起こさないようにするためのものです (コレクションのサイズが変更されました)。

foreach (var item in copyOfMandatory)
{
    if (!mandatoryusers.All(i => mandatory.Contains(i.CertificateValue) 
                            || i.Uid == item.Uid))
    {
         mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
    }
}

UPDATE RemoveAll は、期待どおりに機能しない if ステートメントの魅力のように機能します。

これを行っても、リストのどの部分も取り除かれません。|| の代わりに && で始めました。しかし、それを行うと、検索条件を満たしている限り、最後に遭遇した人以外はすべて殺されます。

これを行う方法についてのヒントはありますか?

4

4 に答える 4

1

あなたのifAll基準がオフです。

if (!mandatoryusers.All(i => mandatory.Contains(i.CertificateValue) 
                        || i.Uid == item.Uid))
{
     mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
}

&&notを使用する必要があり、代わりに||呼び出す必要がありますAny()All()

if (!mandatoryusers.Any(i => mandatory.Contains(i.CertificateValue) 
                            && i.Uid == item.Uid))
{
    mandatoryusers.RemoveAll(i => i.Uid == item.Uid);
}

うまくいけば、あなたの論理と質問が正しく理解できました。

于 2013-05-28T19:35:12.907 に答える
1

あなたのAll呼び出しは十分に細分化されていません: すべてのエントリが常に存在することを確認しようとしています... PER USER のすべてのエントリが存在するわけではありません。

各エントリを辞書に変換してみてください。

var dict = new Dictionary<int, List<ItemType>>();
foreach (var mandatoryItem in mandatoryItems)
{
    List<ItemType> itemTypeValue = null;
    if (!dict.TryGetValue(mandatoryItem.Uid, out itemTypeValue)
    {
        itemTypeValue = new List<ItemType>();
        dict.Add(mandatoryItem.Uid, itemTypeValue);
    }
    itemTypeValue.Add(mandatoryItem);
}

これで、Uid のキーにすべての ItemType ができました。ここから、LINQ を使用します。

mandatoryusers = mandatoryusers.Where(i => dict[i.Uid].All(x => mandatory.Contains(x.CertificateValue));
于 2013-05-28T19:35:36.307 に答える
1

私はそのようなことを試してみます

var uIdToRemove = mandatoryusers.GroupBy(m => m.Uid)
                    .Where(g => mandatory.Except(g.Select(s => s.CertificateValue)).Any())
                    .Select(g => g.Key).ToList();

mandatoryusers.RemoveAll(x => uidToRemove.Contains(x.Uid));
于 2013-05-28T19:39:22.880 に答える
1

あなたの声明は正しくありません(あなたが述べたように)-すべてのアイテムにIDを持つ証明書が含まれているかどうか、またはユーザーIDが現在のアイテムである場所ifを確認しようとしています。あなたがしなければならないことは、最初にユーザーIDでフィルタリングしてから、証明書をチェックすることです. しかし、これは私がする方法ではありません。結果をユーザーごとにグループ化し、証明書を確認しますmandatory

var usersWithAllCertificates = mandatoryUsers.GroupBy(mu => mu.Uid)
             //Select the ones that have all 3 certificates
             .Where(g => g.Select(u => u.CertificateValue)
                 .Intersect(mandatory).Count() == 3)
             .Select(g => g.ToList());

演算子はIntersectリストを結合し、結果は両方のリストで同じ項目になります。したがって、ユーザーが 3 つの証明書 (3、5、および 16) をすべて持っている場合、交差の結果は 3 つのアイテムになります。オブジェクトには、必要なすべてのユーザーが含まれusersWithAllCertificatesます。これは、不要な値を削除するのではなく、必要な値を明示的に選択することです。これは、より良い方法です。これは、各ユーザーがリストに 1 回だけ含まれている (つまり、証明書が 3 つしかない) ことを前提としていることに注意してください。

于 2013-05-28T19:46:17.103 に答える