简体   繁体   English

C# filter 基于类属性的类列表字典

[英]C# filter Dictionary of list of class based on class property

I have this dictionary Dictionary<string, List<Payments>> , which holds employees, each employee having a list of payments.我有这本字典Dictionary<string, List<Payments>> ,其中包含员工,每个员工都有一个付款列表。 The Payments class has a string property named PayCategoryId. Payments 类有一个名为 PayCategoryId 的字符串属性。 I want to filter this dictionary and get only the employees with payments having some specific PayCategoryId values and for each employee only those payments.我想过滤这本字典,只获取支付具有某些特定 PayCategoryId 值的员工,并且只获取每个员工的这些支付。 I'm pretty sure this can be achieved by using LINQ, but I have almost zero experience with LINQ, so need your help.我很确定这可以通过使用 LINQ 来实现,但我对 LINQ 的经验几乎为零,因此需要您的帮助。

The original (unfiltered) dictionary has 76 items (employees).原始(未过滤)字典有 76 个项目(员工)。 The employee which I'll use as an example has 27 payments, some of them having the required PayCategoryId.我将用作示例的员工有 27 笔付款,其中一些具有所需的 PayCategoryId。

What I've done:我所做的:

  1. List with the required PayCategoryId:列出所需的 PayCategoryId:
    var payCategoriesID = new List<string> (){ "a", "b", "c" };
  1. Semi-filter the dictionary with this LINQ (I'm sure it's a mess, but is working!):用这个 LINQ 对字典进行半过滤(我确定这是一团糟,但正在工作!):
    var result = dict.Where(o => o.Value.Where(x => payCategoriesID.Contains(x.PayCategoryId)).Any()).ToDictionary(mc => mc.Key, mc => mc.Value);
  1. The semi-filtered resulted dictionary has only 34 items.半过滤结果字典只有 34 个项目。 The employees having no payments with the required PayCategoryId were filtered out.没有支付所需的 PayCategoryId 的员工被过滤掉。 But my example employee still has all 27 payments in the list.但是我的示例员工仍然拥有列表中的所有 27 笔付款。 I need his list to be filtered too and have only the payments having PayCategoryId = one of the IDs from payCategoriesID list.我也需要过滤他的列表,并且只有 PayCategoryId = payCategoriesID 列表中的 ID 之一的付款。 Of course, the example employee is just an example, all employees should be filtered.当然,示例员工只是一个示例,应该过滤所有员工。

Can you help, please?你能帮忙吗?

Adrian阿德里安

You can use Select() to project into an enumerable of anonymous type and get only the value you want, then build back a dictionary.您可以使用Select()投影到匿名类型的枚举中并仅获取您想要的值,然后再构建一个字典。

var match = dict
        .Select(kv => new
        {
            Employee = kv.Key,
            Payments = kv.Value.Where(p => payCategoriesID.Contains(p.PayCategoryId))
        })
        .Where(emp => emp.Payments.Any())
        .ToDictionary(k => k.Employee, v => v.Payments);

The first step creates an object with key and filtered values, then the Where() remove the empty lists.第一步创建一个带有键值和过滤值的对象,然后Where()删除空列表。 That way you only iterate through the ids list once (per element on the dictionary).这样你只遍历 ids 列表一次(字典中的每个元素)。


Also, not really related, but the Any() method has an overload which takes a predicate, so instead of此外,并不是真正相关,但Any()方法有一个带谓词的重载,因此而不是

o.Value.Where(x => payCategoriesID.Contains(x.PayCategoryId)).Any()

you can do directly你可以直接做

o.Value.Any(x => payCategoriesID.Contains(x.PayCategoryId))

Same goes for other LINQ methods such as Count() , First() , FirstOrDefault() , Last() and more.其他 LINQ 方法也是如此,例如Count()First()FirstOrDefault()Last()等。

var result = dict.Where(o => o.Value.Where(x => payCategoriesID.Contains(x.PayCategoryId)).Any()).ToDictionary(mc => mc.Key, mc => mc.Value.Where(t=> payCategoriesID.Contains(t.PayCategoryId)));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM