使用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#客户端代码。
另一个澄清是,我也可能不提供参数“厨房用具”,可能只想要独特的参数,例如它将返回厨房用具和起居室,只有类似于一个类别,无论多少类型有。
灵活的方法
使用GroupBy
和ToDictionary
创建在Type
属性上Type
的List
值的字典:
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
),或者您可以将Distinct
与Select
结合使用以避免需要实现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();