使用LINQ的唯一项目列表

我一直在使用LINQ一段时间了,但似乎被困在关于Unique项目的东西上,我有下面的列表:

List stock = new List(); 

它具有以下属性:字符串ID,字符串类型,字符串描述,示例:

 public class Stock { public string ID { get; set; } public string Type { get; set; } public string Description { get; set; } } 

我希望有一个LINQ查询,它将按照类型对库存中的项目进行分组,并将其作为新的库存列表返回(它必须与原始库存列表的类型相同)。

示例数据:

  ID Type Description ---------------------------------------------- 1 Kitchen Appliance Dishwasher 2 Living Room Television 3 Kitchen Appliance Washing Machine 4 Kitchen Appliance Fridge 

我的Linq查询希望能够返回所有的厨房用具示例。
所以我将它作为“类型”传递给查询,它将返回此示例列表中的项目1,3和4。

返回的列表也必须是类型: List

基本上我想要一个按类型列出的唯一项目,类似于SQL Distinct查询,我如何在LINQ中实现这一点?
替代解决方案很好,但必须只是Silverlight / C#客户端代码。

另一个澄清是,我也可能不提供参数“厨房用具”,可能只想要独特的参数,例如它将返回厨房用具和起居室,只有类似于一个类别,无论多少类型有。

灵活的方法

使用GroupByToDictionary创建在Type属性上TypeList值的字典:

 var appliancesByType = stock .GroupBy(item => item.Type) .ToDictionary(grp => grp.Key, grp => grp.ToList()); 

然后,您可以非常轻松地访问类型本身以及任何给定类型的列表:

 // List of unique type names only List stockTypes = appliancesByType.Keys.ToList(); // Or: list of one stock item per type List exampleStocks = appliancesByType .Select(kvp => kvp.Value[0]) .ToList(); // List of stock items for a given type List kitchenAppliances = appliancesByType["Kitchen Appliance"]; 

正如我所看到的,这种方法真正满足了您的所有需求。 但对于其他一些选项,请参见下文。

替代(快速和肮脏)的方法

你总是可以使用Where来获取你想要的类型的项目,然后ToList将这些项目放在一个新的List

 List kitchenAppliances = stock .Where(item => item.Type == "Kitchen Appliance") .ToList(); 

回应这最后一部分:

另一个澄清是,我也可能不提供参数“厨房用具”,可能只想要独特的参数,例如它将返回厨房用具和起居室,只有类似于一个类别,无论多少类型有。

在这里,你似乎想要一些完全不同的东西:基本上是Distinct提供的行为。 对于此function,您基本上可以使用Soonts的答案 (可选地,返回IEnumerable而不是IEnumerable ),或者您可以将DistinctSelect结合使用以避免需要实现IEqualityComparer (见下文)。


更新

在回应您的澄清时,这是我的建议:两种方法,一种用于各种目的( 单一责任原则 ):

 // This will return a list of all Stock objects having the specified Type static List GetItemsForType(string type) { return stock .Where(item => item.Type == type) .ToList(); } // This will return a list of the names of all Type values (no duplicates) static List GetStockTypes() { return stock .Select(item => item.Type) .Distinct() .ToList(); } 

听起来这是一个简单的Where子句需要。

 List kitchen= stock.Where(s=>s.Type=="Kitchen Appliance") .OrderBy(s=>s.Description).ToList(); 

如果您想严格要求源列表中包含的Types

string[] typesFound = stock.Select(s=>s.Type).Distinct().ToArray();

 static class EnumerableEx { // Selectively skip some elements from the input sequence based on their key uniqueness. // If several elements share the same key value, skip all but the 1-st one. public static IEnumerable uniqueBy( this IEnumerable src, Func keySelecta ) { HashSet res = new HashSet(); foreach( tSource e in src ) { tKey k = keySelecta( e ); if( res.Contains( k ) ) continue; res.Add( k ); yield return e; } } } // Then later in the code List res = src.uniqueBy( elt => elt.Type ).ToList() 
 var kitchenAppliances = stocks.Where(stock => stock.Type == "Kitchen Appliance"); 

我可能不明白这个问题,但这听起来像一个非常简单的Linq查询:

 List stock = new List(); ... populate your list as per your example List kitchenAppliances = (from obj in stock where obj.Type == "Kitchen Appliance" select obj).ToList(); 

或者如果您更喜欢扩展方法语法:

 List kitchenAppliances = stock.Where(obj => obj.Type == "Kitchen Appliance").ToList(); 

我不明白的是你在这种情况下使用的是独特和独特的。 对象已经是独一无二的,在我看来,你想要一个基本的查询“给我所有的厨房用具”。

你也可以沿着这些方向做一些事情,在这种情况下我采取lucene结果然后将umbraco节点拉到匿名类型

 var datasource = (from n in SearchResults select new { PageLink = uQuery.GetNode(n.Id).NiceUrl, uQuery.GetNode(n.Id).Name, Date = uQuery.GetNode(n.Id).GetProperty("startDate"), IntroText = string.IsNullOrEmpty(uQuery.GetNode(n.Id).GetProperty("introText").Value) ? string.Empty : uQuery.GetNode(n.Id).GetProperty("introText").Value, Image = ImageCheck(uQuery.GetNode(n.Id).GetProperty("smallImage").Value) }).Distinct().ToList();