我一直在使用LINQ一段时间了,但似乎是关于Unique项目的问题,我有下面的列表:
List<Stock> stock = new List<Stock>();
它具有以下属性:字符串ID,字符串类型,字符串描述,示例:
public class Stock
{
public string ID { get; set; }
public string Type { get; set; }
public string Description { get; set; }
}
我希望有一个LINQ查询,它会按照类型对Stock中的项目进行分组,并将其作为新的Stock列表返回(它必须与原始Stock List的类型相同)。
示例数据:
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<Stock>
类型。
基本上我想要一个按类型列出的唯一项目,类似于SQL Distinct查询,如何在LINQ中实现这一点?
替代解决方案很好,但必须只是Silverlight / C#客户端代码。
另一个澄清是,我也可能不提供参数“厨房用具”,可能只想要独特的参数,例如,它将返回厨房用具和起居室,只有一个类似于一个类别,无论多少那种类型有。
答案 0 :(得分:44)
使用GroupBy
和ToDictionary
创建List<Stock>
属性上键入的Type
值字典:
var appliancesByType = stock
.GroupBy(item => item.Type)
.ToDictionary(grp => grp.Key, grp => grp.ToList());
然后,您可以非常轻松地访问类型本身以及任何给定类型的列表:
// List of unique type names only
List<string> stockTypes = appliancesByType.Keys.ToList();
// Or: list of one stock item per type
List<Stock> exampleStocks = appliancesByType
.Select(kvp => kvp.Value[0])
.ToList();
// List of stock items for a given type
List<Stock> kitchenAppliances = appliancesByType["Kitchen Appliance"];
正如我所看到的,这种方法确实可以满足您的所有需求。但是对于其他一些选项,请参见下文。
您始终可以使用Where
来获取所需类型的项目,然后ToList
将这些项目放入新的List<Stock>
:
List<Stock> kitchenAppliances = stock
.Where(item => item.Type == "Kitchen Appliance")
.ToList();
回应最后一部分:
另一个澄清是我 也可能不提供参数 “厨房用具”可能只是想要 独特的,例如它会 返回厨房用具和生活 房间一次,每次只有一种像 类别,无论多少 输入有。
在这里,您似乎想要完全不同的东西:基本上是Distinct
提供的行为。对于此功能,您基本上可以使用Soonts's answer(可选地,返回IEnumerable<tKey>
而不是IEnumerable<tSource>
),或者您可以将Distinct
与{{3}结合使用}避免需要实现IEqualityComparer<Stock>
(见下文)。
回应您的澄清,这是我的建议:两种方法,每种方法一种(Select
):
// This will return a list of all Stock objects having the specified Type
static List<Stock> 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<string> GetStockTypes()
{
return stock
.Select(item => item.Type)
.Distinct()
.ToList();
}
答案 1 :(得分:4)
听起来像是一个简单的Where子句需要。
List<Stock> kitchen= stock.Where(s=>s.Type=="Kitchen Appliance")
.OrderBy(s=>s.Description).ToList();
如果您想严格要求源列表中包含的Types
:
string[] typesFound = stock.Select(s=>s.Type).Distinct().ToArray();
答案 2 :(得分:3)
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<tSource> uniqueBy<tSource, tKey>( this IEnumerable<tSource> src, Func<tSource, tKey> keySelecta )
{
HashSet<tKey> res = new HashSet<tKey>();
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<Stock> res = src.uniqueBy( elt => elt.Type ).ToList()
答案 3 :(得分:3)
var kitchenAppliances = stocks.Where(stock => stock.Type == "Kitchen Appliance");
答案 4 :(得分:1)
我可能不明白这个问题,但这听起来像是一个非常简单的Linq查询:
List<Stock> stock = new List<Stock>();
... populate your list as per your example
List<Stock> kitchenAppliances =
(from obj in stock
where obj.Type == "Kitchen Appliance"
select obj).ToList();
或者您更喜欢扩展方法语法:
List<Stock> kitchenAppliances =
stock.Where(obj => obj.Type == "Kitchen Appliance").ToList();
我不明白的是你在这种情况下对独特和独特的使用。对象已经是唯一的,在我看来,你想要一个基本的查询“给我所有的厨房用具”。
答案 5 :(得分:1)
你也可以沿着这些方向做一些事情,在这种情况下我采取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();