对嵌套对象按linq分组
本文关键字:linq 分组 对象 嵌套 | 更新日期: 2023-09-27 18:01:22
我正在制作一个由linq语句组成的组,其中我将单个数据列表转换为具有嵌套列表的列表。下面是我到目前为止的代码:
[TestMethod]
public void LinqTestNestedSelect2()
{
// initialization
List<combi> listToLinq = new List<combi>() {
new combi{ id = 1, desc = "a", name = "A", count = 1 },
new combi{ id = 1, desc = "b", name = "A", count = 2 },
new combi{ id = 2, desc = "c", name = "B", count = 3 },
new combi{id = 2, desc = "d", name = "B", count = 4 },
};
// linq group by
var result = (from row in listToLinq
group new { des = row.desc, count = row.count } by new { name = row.name, id = row.id } into obj
select new A { name = obj.Key.name, id = obj.Key.id, descriptions = (from r in obj select new B() { des = r.des, count = r.count }).ToList() }).ToList();
// validation of the results
Assert.AreEqual(2, result.Count);
Assert.AreEqual(2, result[0].descriptions.Count);
Assert.AreEqual(2, result[0].descriptions.Count);
Assert.AreEqual(2, result[1].descriptions.Count);
Assert.AreEqual(2, result[1].descriptions.Count);
}
public class A
{
public int id;
public string name;
public List<B> descriptions;
}
public class B
{
public int count;
public string des;
}
public class combi
{
public int id;
public string name;
public int count;
public string desc;
}
如果对象像示例一样小,这很好。然而,我将为具有更多属性的对象实现这一点。我怎样才能有效地编写这条语句,这样我就不必在linq语句中写两次字段名了?
我想返回语句中的对象,我想要这样的:
// not working wishfull thinking code
var result = (from row in listToLinq
group new { des = row.desc, count = row.count } by new { name = row.name, id = row.id } into obj
select new (A){ this = obj.key , descriptions = obj.ToList<B>()}).ToList();
Background:我正在重写一个web api,检索对象嵌套的对象在一个单一的数据库调用db性能的缘故。它基本上是一个大的查询与连接检索垃圾负载的数据,我需要整理成对象。
可能很重要: ID是唯一的
根据到目前为止的答案,我已经制定了一个解决方案,它对我来说是有效的,但仍然有点丑,我希望它更好看。
{
// start part
return (from row in reader.AsEnumerable()
group row by row.id into grouping
select CreateA(grouping)).ToList();
}
private static A CreateA(IGrouping<object, listToLinq> grouping)
{
A retVal = StaticCreateAFunction(grouping.First());
retVal.descriptions = grouping.Select(item => StaticCreateBFunction(item)).ToList();
return ret;
}
我希望staticcreatefunction对于它的作用是足够明显的。在这种情况下,我只需要写出每个属性一次,这正是我真正想要的。但我希望有一个更聪明的方式来写这个
var result = (from row in listToLinq
group new B { des = row.desc, count = row.count } by new A { name = row.name, id = row.id } into obj
select new A { name = obj.Key.name, id = obj.Key.id, descriptions = obj.ToList() }).ToList();
您可以向每个A
和B
类添加一个构造函数,该构造函数接收combi
,然后它只从中获取所需的内容。例如对于a
:
public class A
{
public A(combi c)
{
id = c.id;
name = c.name;
}
}
public class B
{
public B(combi c)
{
count = c.count;
des = c.desc;
}
}
那么你的查询可以看起来像:
var result = (from row in listToLinq
group row by new { row.id, row.name } into grouping
select new A(grouping.First())
{
descriptions = grouping.Select(item => new B(item)).ToList()
}).ToList();
如果你不喜欢grouping.First()
,你可以覆盖Equals
和GetHashCode
,然后在group by
中通过一个新的a
做相关字段(这将是Equals
中的那些),然后从a
中添加copy constructor
A
/B
类与combi
解耦的另一种方法是将转换逻辑提取为静态方法的集合。