使用linq在一个属性c#上过滤两个列表

nit*_*igo 6 c# linq

我有两个对象,即交易:

Card:
public string CardID {get; set;}
public string TransactionRef {get; set;}

Transaction:
public string TxnID {get; set;}
public string TxnDetails {get; set;}
Run Code Online (Sandbox Code Playgroud)

注:TransactionRef是格式的Date|TxnID

我还有两个对象的列表List<Card> cardDetailsList<Transaction> transDetails

cardDetails:
{CardID = '1', TransactionRef = '20150824|Guid1'}
{CardID = '2', TransactionRef = '20150824|Guid2'}
{CardID = '3', TransactionRef = '20150824|Guid3'}

transDetails:
{TxnID = '23', TxnDetails = 'Guid1'}
{TxnID = '24', TxnDetails = 'Guid2'}
Run Code Online (Sandbox Code Playgroud)

我想使用基于TxnDetails的transDetails过滤cardDetails,以便过滤掉第二个列表中不包含TxnDetails的项目.

这应该是输出:

cardDetails:
 {CardID = '3', TransactionRef = '20150824|Guid3'}
Run Code Online (Sandbox Code Playgroud)

我试过这样使用linq:

  cardDetails = cardDetails.Where(x => transDetails.Any(y => x.TransactionRef.Contains(y.TxnDetails) == false)).ToList();
Run Code Online (Sandbox Code Playgroud)

但它总是将列表返回为空白.我已尝试此查询的许多变体但没有成功.我知道在搜索它们之前和之后已经问过这个问题,并且尝试了他们的解决方案我仍然无法做到正确.

任何人都可以建议我的查询有什么问题吗?

注意:我忘了提到的一件事是这些列表可以包含1000条记录.所以表现也很重要.

dca*_*tro 6

这应该做到这一点

var cards = 
    from card in cardDetails
    let txnDetails = GetTxnDetails(card)
    where ! transDetails.Any(t => t.TxnDetails == txnDetails)
    select card;


static string GetTxnDetails(Card card)
{
    return card.TransactionRef.Split('|')[1];
}
Run Code Online (Sandbox Code Playgroud)

小提琴:https://dotnetfiddle.net/b9ylFe


优化这一点的一种方法是将所有可能的事务细节存储在哈希集中.然后,查找应非常接近O(1)(假设公平的哈希码分布)而不是O(n) - 使算法的总体复杂度从O(n*k)下降到O(n + k).

var allTxnDetails = new HashSet<string>(transDetails.Select(t => t.TxnDetails));

var cards = 
    from card in cardDetails
    let txnDetails = GetTxnDetails(card)
    where ! allTxnDetails.Contains(txnDetails)
    select card;
Run Code Online (Sandbox Code Playgroud)

小提琴:https://dotnetfiddle.net/hTYCbj