使用LINQ过滤包含复杂类型的字典 [英] Filter a dictionary which contains complex type using LINQ

查看:105
本文介绍了使用LINQ过滤包含复杂类型的字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,



我正在使用API​​为我提供以下收藏:

字典<字符串,列表<产品>> 





关键是产品代码,值是包含实际的列表产品对象。



C#应用程序中的Product实体包含以下属性:

Product_ID

Product_NAME

Product_DESC

Product_CODE

Product_TYPE




Product_TYPE C#应用程序中的实体是一个复杂类型,包含以下属性:

Product_TYPE_CODE

Product_TYPE_DESC




Product_Code和Product_Type可以为null,因为数据库中的那些列也可以设置为null。



我的应用程序中的最终用户提供Product_codes和/或Product_types的列表。现在关于ProductType List,如果值为UNKNOWN,我想在该特定属性的null值上匹配该值,并将其替换为UNKNOWN。



所以说我有ProductTypes列表,列表包含值UNKNOWN我希望在C#实体的ProductType属性上匹配它。



怎么能我是用LINQ做的吗?



我很感谢有关上述内容的帮助/建议。



< b>我尝试了什么:



我尝试了以下来自API的代码,但我很难使用LINQ来过滤产品提供的ProductTypes和ProductCodes列表并替换ProductType属性:



var loadedProducts = ProductFactory.GetAll();



此方法基本上从db获取产品并适当地缓存它们。调用此方法的返回值是

 Dictionary< string,list< product>>()





LINQ是否适合在此上下文中使用,或者使用LINQ不是一个好主意?



我可以通过在SQL中执行以下操作来按PRODUCT_CODE和PRODUCT_TYPE过滤产品(这仍在进行中,但我想展示到目前为止我能做些什么在SQL)。



 SELECT PRODUCT_ID,
PRODUCT_CODE,
COALESCE(PRODUCT_TYPE,' UNKNOWN' PRODUCT_TYPE,
PRODUCT_DESC,
FROM PRODUCTS
WHERE PRODUCT_CODE IN(' TYAHAH' ABH989'
AND COALESCE(PRODUCT_TYPE,' UNKNOWN')IN(' ABC'' UNKNOWN');

解决方案

  //  假设这些是填充的(或者至少是没有元素的实例化) 
List< string> userProductCodes;
List< string> userTypeCodes;

字典<字符串,列表< product = >> loadedProducts;

List< string> matchingList = loadedProducts
.Where(kv => userProductCodes.Contains(kv.Key)) // 选择只有密钥位于userProductCodes列表中的项目
.Select(kv => kv.Value) // 将键/值对(即列表)的值分开,因此我们现在有一个列表,其列表具有适当的PRODUCT_CODE
.Aggregate( new List< string>(),(newList,oldList)= > {newList.AddRange(oldList); return newList;}) // 现在我们将所有列表合并到一个单一的大清单
.Where(product => userTypeCode.Contains(product.TYPE_CODE ?? UNKNOWN)) // 匹配用户类型代码 - 用UNKNOWN替换null用于检查
.ToList(); // 将结果转换为列表。





注意:这是一个AND类型的结果,即产品代码在用户列表中的产品,类型代码在用户类型列表中。

要创建OR类型列表,请从键/值对中删除选择产品代码的行,并扩展选择类型代码的Where,使其具有|| userProductCode.Contains(product.PRODUCT_CODE)as它的条件。


这使它更简单 - 有两种方法。整个事物中只有一个 Where 。您可以使用密钥检查PRODUCT_CODE,也可以只处理值并检查产品和类型代码。



选项1:

 loadedProducts.Where(kv => userProductCodes.Contains(kv.Key)&& userTypeCodes.Contains(kv.Value.TYPE_CODE ??   UNKNOWN



或者,只是使用值集合

 loadedProducts.Values.Where(product => userProductCodes.Contains(product.PRODUCT_CODE)&& userTypeCodes.Contains(product => product.TYPE_CODE ??   UNKNOWN





再次,上面的返回记录两个参数都为真(即PRODUCT_CODE和TYPE_CODE都出现在相应的列表中)。只需将&& 更改为 || 如果你想要的结果是真的。



实际上,这个问题是我写的最新Tip / Trick文章灵感的一部分 - 阅读它,它可以帮助你理解如何为自己实现这类事情。

查找与......之一匹配的集合中的项目 [ ^ ]


Hi there,

I am working with an API which provides me with the following collection:

Dictionary<string,list<product>>



The key is the Product Code and the value is a list contains the actual Product object.

The Product entity in the C# application contains the following properties:
Product_ID
Product_NAME
Product_DESC
Product_CODE
Product_TYPE


Product_TYPE entity in the C# application is a complex type and contains the following properties:
Product_TYPE_CODE
Product_TYPE_DESC


The Product_Code and Product_Type can be null because those columns in the database are can be set to null as well.

The end user in my application provides a list of Product_codes and/or Product_types. Now regarding the ProductType List, if the value is "UNKNOWN" i would like to match that value on the null value for that particular property and substitute it for "UNKNOWN".

So say i have list of ProductTypes and the list contains value of "UNKNOWN" i want to match that on the ProductType property of the C# entity.

How can i go about doing this using LINQ?

I appreciate assistance/advice regarding the above.

What I have tried:

I tried the following code which comes from the API but i am having difficulty using LINQ to filter the products out using the provided List of ProductTypes and ProductCodes and substitute the ProductType property:

var loadedProducts = ProductFactory.GetAll();

This method essentially gets the products from the db and caches them appropriately. The return value from invoking this method is

Dictionary<string,list<product>>()



Is LINQ appropriate to use in this context or is it not a good idea to use LINQ?

I can filter the Products by PRODUCT_CODE and PRODUCT_TYPE by doing the following in SQL(this is still in work in progress but i wanted to demonstrate what i can do so far in SQL).

SELECT PRODUCT_ID,
 PRODUCT_CODE,
COALESCE(PRODUCT_TYPE, 'UNKNOWN') as PRODUCT_TYPE,
PRODUCT_DESC,
FROM PRODUCTS
WHERE PRODUCT_CODE IN ('TYAHAH','ABH989')
AND COALESCE(PRODUCT_TYPE, 'UNKNOWN') IN ('ABC','UNKNOWN');

解决方案

// Assuming these are populated (or at very least, Instantiated with no elements)
List<string> userProductCodes;
List<string> userTypeCodes;

Dictionary<string, list<product="">> loadedProducts;

List<string> matchingList = loadedProducts
	.Where(kv=>userProductCodes.Contains(kv.Key)) // Selects only items where the key is in the userProductCodes list
	.Select(kv=>kv.Value) // separates out the value of the Key/Value pairs (i.e. the lists), so we now have a list of lists that have an appropriate PRODUCT_CODE
	.Aggregate(new List<string>(), (newList, oldList)=>{ newList.AddRange(oldList); return newList;}) // Now we have combined all the lists into one single big list
	.Where (product=>userTypeCode.Contains(product.TYPE_CODE ?? "UNKNOWN")) // Match the User Type codes up - replaces null with "UNKNOWN" for the check
	.ToList(); // Converts the result to a list.



Note: This is an "AND" type result i.e. The Products where the Product code is in the user list AND the type code is in the user Type list.
To make an OR type list, remove the line that selects the product code from the key/value pairs, and extend the Where that selects the type code so that is has an "|| userProductCode.Contains(product.PRODUCT_CODE)" as its condition.


This makes it much simpler - and there are 2 approaches. There will only be one Where in the entire thing. You can either use the key to check the PRODUCT_CODE, or just process the values and check for both product and type codes there.

Option 1:

loadedProducts.Where(kv=>userProductCodes.Contains(kv.Key) && userTypeCodes.Contains(kv.Value.TYPE_CODE ?? "UNKNOWN")


or, just using the values collection

loadedProducts.Values.Where(product=>userProductCodes.Contains(product.PRODUCT_CODE) && userTypeCodes.Contains(product=>product.TYPE_CODE ?? "UNKNOWN")



Once again, the above returns record where both parameters are true (i.e. Both PRODUCT_CODE and TYPE_CODE occur in respective lists). Just change the && to || if you want results where either are true.

Actually, this question was part of the inspiration of the latest Tip/Trick article I wrote - have a read of it, it may help you understand just how to achieve this sort of thing for yourself.
Finding Items in a Collection that Match one of...[^]


这篇关于使用LINQ过滤包含复杂类型的字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆