C# 林克。按对象名称属性或名称部分搜索对象

C# 林克。按对象名称属性或名称部分搜索对象,c#,linq,object,search,C#,Linq,Object,Search,我试图找到所有发票的买家,按买家名称搜索包含和等于过滤器。正在寻找最干净的方法。 我有一份买家名单 List <Buyer> AllBuyers; 我有一份给买家的发票清单 List <Invoice> AllInvoices; 我目前正在做的事情: List<string> BuyerIDs = new List<string> { }; foreach (Invoice inv in AllInvoices) { if (!(Buy

我试图找到所有发票的买家,按买家名称搜索包含和等于过滤器。正在寻找最干净的方法。 我有一份买家名单

List <Buyer> AllBuyers;
我有一份给买家的发票清单

List <Invoice> AllInvoices;
我目前正在做的事情:

List<string> BuyerIDs = new List<string> { };
foreach (Invoice inv in AllInvoices)
{
    if (!(BuyerIDs.Contains(inv.BuyerID)))
    {
         // add BuyerID to list if it's not already there. Getting id's that are present on invoices and whose Buyer names match using contains or equals
        BuyerIDs.Add(AllBuyers.First(b => b.BuyerIdentifier == inv.BuyerID
          && (b.Name.IndexOf(SearchValue, StringComparison.OrdinalIgnoreCase) >= 0)).BuyerIdentifier);
    }                                                
 }
 Invoices = AllInvoices.FindAll(i=> BuyerIDs.Contains(i.BuyerID));

以下是我创建一个字典的建议,其中BuyerIdentifier作为键,发票列表作为值:

var dict = AllBuyers.ToDictionary(k => k.BuyerIdentifier,
                v => AllInvoices.Where(i => i.BuyerID == v.BuyerIdentifier).ToList());
然后,您可以访问特定买家的发票列表,如下所示:

List<Invoice> buyerInvoices = dict[buyerId];

这应该适合您:

var InvoiceGrouping = AllInvoices.GroupBy(invoice => invoice.BuyerID)
                                 .Where(grouping => AllBuyers.Any(buyer => buyer.BuyerIdentifier == grouping.Key && buyer.Name.IndexOf(pair.Value, StringComparison.OrdinalIgnoreCase) >= 0));
最终得到的是一个分组,该分组以买方ID为键,所有发票为值

如果您只需要发票的平面列表,可以这样做:

var Invoices = AllInvoices.GroupBy(invoice => invoice.BuyerID)
                          .Where(grouping => AllBuyers.Any(buyer => buyer.BuyerIdentifier == grouping.Key && buyer.Name.IndexOf(pair.Value, StringComparison.OrdinalIgnoreCase) >= 0))
                          .SelectMany(grouping => grouping);

请注意末尾添加的SelectMany,由于IGrouping实现了IEnumerable,因此它将分组扁平化为单个值枚举。

如果您只需要发票,您可以加入两个集合,过滤并选择发票

AllBuyers.Join(AllInvoices, 
            a => a.BuyerIdentifier, 
            a => a.BuyerID, 
            (b, i) => new { Buyer = b, Invoice = i })
    .Where(a => a.Buyer.Name.Contains("name"))
    .Select(a => a.Invoice).ToList();
如果您也需要买家,只需省略.Selecta=>a.Invoice即可。 字符串的Contains方法也将匹配equals。

作为ILookup粉丝,这将是我的方法:

var buyerMap = AllBuyers
    .Where(b => b.Name.IndexOf(SearchValue, StringComparison.OrdinalIgnoreCase) >= 0)
    .ToDictionary(b => b.BuyerIdentifier);

var invoiceLookup = AllInvoices
    .Where(i => buyerMap.ContainsKey(i.BuyerID))
    .ToLookup(x => x.BuyerID);

foreach (var invoiceGroup in invoiceLookup)
{
    var buyerId = invoiceGroup.Key;
    var buyer = buyerMap[buyerId];
    var invoicesForBuyer = invoiceGroup.ToList();

    // Do your stuff with buyer and invoicesForBuyer
}

你的代码有效吗?如果确实如此,并且您只是想改进代码,那么这个问题可能属于,而不是这里。否则,您遇到了什么问题,或者您看到了什么错误?它是有效的,我只是想知道在LINQ中是否有更好的方法来完成它,而无需foreach循环和if条件。我不知道您在做什么,但您可能只是在做一个连接。什么是pair.Value?看起来有东西丢了,忘了换那个了。这是搜索值。这是非常低效的。谢谢,我想加入是我一直在寻找的。至于Contains,我想要不区分大小写的搜索,不想使用toLower。我想在执行加入之前过滤买家会让你受益匪浅。我想这就是OP上次编辑后的意图。也就是说,他打算通过名字上的搜索值来过滤买家,这可能会大大减少买家的完整列表。只有一个加入的警告,如果你不能保证每个买家在列表中只出现一次,你会在结果中得到重复的发票。实际上,你不需要查找,GroupBy就足够了,而且可能更干净
var Invoices = AllInvoices.GroupBy(invoice => invoice.BuyerID)
                          .Where(grouping => AllBuyers.Any(buyer => buyer.BuyerIdentifier == grouping.Key && buyer.Name.IndexOf(pair.Value, StringComparison.OrdinalIgnoreCase) >= 0))
                          .SelectMany(grouping => grouping);
AllBuyers.Join(AllInvoices, 
            a => a.BuyerIdentifier, 
            a => a.BuyerID, 
            (b, i) => new { Buyer = b, Invoice = i })
    .Where(a => a.Buyer.Name.Contains("name"))
    .Select(a => a.Invoice).ToList();
var buyerMap = AllBuyers
    .Where(b => b.Name.IndexOf(SearchValue, StringComparison.OrdinalIgnoreCase) >= 0)
    .ToDictionary(b => b.BuyerIdentifier);

var invoiceLookup = AllInvoices
    .Where(i => buyerMap.ContainsKey(i.BuyerID))
    .ToLookup(x => x.BuyerID);

foreach (var invoiceGroup in invoiceLookup)
{
    var buyerId = invoiceGroup.Key;
    var buyer = buyerMap[buyerId];
    var invoicesForBuyer = invoiceGroup.ToList();

    // Do your stuff with buyer and invoicesForBuyer
}