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
}