C#集团由几个嵌套属性和列表值 [英] C# Group By Several Nested Properties And List values
问题描述
我有这样的对象结构:
公共类根
{
公众诠释值1;
公众诠释值2;
公开名单< NestedA> NestedAList;
}
公共类NestedA
{
公开名单< NestedB> NestedBList;
公开名单< NestedC> NestedCList;
}
公共类NestedB {
公众诠释VALUEB;
公众诠释ValueB2;
}
公共类NestedC {
公众诠释ValueC;
公众诠释ValueC2;
}
我需要使用所有的值从根类组根对象和它的嵌套的列表。
我一直在玩弄了一会儿,无法弄清楚如何/或如果我可以声明为此在单个组,或者什么是最好的方式来acomplish这可能是。
编辑:我需要通过根的属性,嵌套在属性,嵌套在b属性和嵌套ç属性分组的项目。
因此,它是有道理的:我的真实对象有更多的属性,只是显示我需要进行分组的那些,并且可以作为一个起点使用
谢谢前进。
如果我们有这个元素
根
值1 = 1
值2 = 2
NestedAList =
{NestedBList =
{VALUEB = 2,ValueB2 = 3}
]
NestedCList = [
{ValueC = 5,ValueC2 = 11}
]}
]
应该与分组这样的:
根
值1 = 1
值2 = 2
NestedAList =
{NestedBList =
{VALUEB = 2,ValueB2 = 3}
]
NestedCList =
{ValueC = 5, ValueC2 = 11}
]}
]
但不是这一个:
根
值1 = 1
值2 = 2
NestedAList =
{NestedBList =
{VALUEB = 2,ValueB2 = 3},{VALUEB = 1,ValueB2 = 4}
]
NestedCList =
{ValueC = 5,ValueC2 = 11}
]}
]
要完成这个任务,你可以覆盖等于()
和的GetHashCode()
的层次结构中的每一个类的方法。这可能是有点棘手,例如,像这样的:
公共类根
{
公众诠释值1;
公众诠释值2;
公开名单< NestedA> NestedAList;
公众覆盖布尔等于(obj对象)
{
根等= OBJ为根;
如果(其他== NULL)返回false;
返回this.Value1 == other.Value1&放大器;&安培; this.Value2 == other.Value2&放大器;&安培; this.NestedAList.SequenceEqual(other.NestedAList);
}
公共覆盖INT的GetHashCode()
{
选中
{
INT波沙= 19;
的foreach(NestedA娜在NestedAList)
{
波沙=波沙* 31 + na.GetHashCode();
}
回报率(值1 ^ ^值1波沙).GetHashCode();
}
}
}
公共类NestedA
{
公开名单< NestedB> NestedBList;
公开名单< NestedC> NestedCList;
公众覆盖布尔等于(obj对象)
{
NestedA其他= OBJ时NestedA;
如果(其他== NULL)返回false;
返回NestedBList.SequenceEqual(other.NestedBList)及和放大器; NestedCList.SequenceEqual(other.NestedCList);
}
公共覆盖INT的GetHashCode()
{
选中
{
INT hashb = 19;
的foreach(在NestedBList NestedB NB)
{
hashb = hashb * 31 + nb.GetHashCode();
}
INT hashc = 19;
的foreach(在NestedCList NestedC NC)
{
hashc = hashc * 31 + nc.GetHashCode();
}
回报率(hashb ^ hashc).GetHashCode();
}
}
}
公共类NestedB {
公众诠释VALUEB;
公众诠释ValueB2;
公众覆盖布尔等于(obj对象)
{
NestedB其他= OBJ时NestedB;
如果(其他== NULL)返回false;
返回this.ValueB == other.ValueB&放大器;&安培; this.ValueB2 == other.ValueB2;
}
公共覆盖INT的GetHashCode()
{
回报率(VALUEB ^ ValueB2).GetHashCode();
}
}
公共类NestedC {
公众诠释ValueC;
公众诠释ValueC2;
公众覆盖布尔等于(obj对象)
{
NestedC其他= OBJ时NestedC;
如果(其他== NULL)返回false;
返回this.ValueC == other.ValueC&放大器;&安培; this.ValueC2 == other.ValueC2;
}
公共覆盖INT的GetHashCode()
{
回报率(ValueC ^ ValueC2).GetHashCode();
}
}
之后,你可以很容易地选择唯一根(每一个独特的根代表一个组):
roots.Distinct()了ToList()
使用 GoupBy()
同样的结果:
roots.GroupBy(R = GT; R)。选择(G => g.First())。了ToList()
计算每个组中的元素:
根。 GROUPBY(R = GT; R)。选择(G => g.Count())
枚举第一组中的元素:
roots.GroupBy(R = GT; R)。首先()选择(G = > G)
如果你不关心元素的订购列表,使用 Enumerable.All
而不是 SequenceEqual
编辑:另外,在这种情况下,你必须改变哈希代码生成alghoritm。例如,像这样: hashb = hashb + nb.GetHashCode()* 31;
(约合可能算法的这里)
I have this object structure:
public class Root
{
public int Value1;
public int Value2;
public List<NestedA> NestedAList;
}
public class NestedA
{
public List<NestedB> NestedBList;
public List<NestedC> NestedCList;
}
public class NestedB{
public int ValueB;
public int ValueB2;
}
public class NestedC{
public int ValueC;
public int ValueC2;
}
I need to group root objects using all Values from Root class and it's nested lists. I've been playing around a while and can't figure out how to/or if I can do this in a single group by statement, or what the best approach to acomplish this could be.
Edit: I need the items grouped by Root properties, Nested A Properties, Nested B Properties and Nested C Properties. So it makes sense: My real objects have more properties, just showing the ones that I need grouped, and can use as a start point.
Thanks in advance.
If we have this element
Root
Value1 = 1
Value2 = 2
NestedAList = [
{NestedBList = [
{ValueB=2, ValueB2=3}
]
NestedCList = [
{ValueC=5, ValueC2=11}
]}
]
it should be grouped with this one:
Root
Value1 = 1
Value2 = 2
NestedAList = [
{NestedBList = [
{ValueB=2, ValueB2=3}
]
NestedCList = [
{ValueC=5, ValueC2=11}
]}
]
but not with this one:
Root
Value1 = 1
Value2 = 2
NestedAList = [
{NestedBList = [
{ValueB=2, ValueB2=3}, { ValueB= 1, ValueB2=4}
]
NestedCList = [
{ValueC=5, ValueC2=11}
]}
]
To accomplish this task, you can override Equals()
and GetHashCode()
methods for each class in your hierarchy. It may be little tricky, for example, like this:
public class Root
{
public int Value1;
public int Value2;
public List<NestedA> NestedAList;
public override bool Equals(object obj)
{
Root other = obj as Root;
if (other == null) return false;
return this.Value1 == other.Value1 && this.Value2 == other.Value2 && this.NestedAList.SequenceEqual(other.NestedAList);
}
public override int GetHashCode()
{
unchecked
{
int hasha = 19;
foreach (NestedA na in NestedAList)
{
hasha = hasha * 31 + na.GetHashCode();
}
return (Value1 ^ Value1 ^ hasha).GetHashCode();
}
}
}
public class NestedA
{
public List<NestedB> NestedBList;
public List<NestedC> NestedCList;
public override bool Equals(object obj)
{
NestedA other = obj as NestedA;
if (other == null) return false;
return NestedBList.SequenceEqual(other.NestedBList) && NestedCList.SequenceEqual(other.NestedCList);
}
public override int GetHashCode()
{
unchecked
{
int hashb = 19;
foreach (NestedB nb in NestedBList)
{
hashb = hashb * 31 + nb.GetHashCode();
}
int hashc = 19;
foreach (NestedC nc in NestedCList)
{
hashc = hashc * 31 + nc.GetHashCode();
}
return (hashb ^ hashc).GetHashCode();
}
}
}
public class NestedB{
public int ValueB;
public int ValueB2;
public override bool Equals(object obj)
{
NestedB other = obj as NestedB;
if (other == null) return false;
return this.ValueB == other.ValueB && this.ValueB2 == other.ValueB2;
}
public override int GetHashCode()
{
return (ValueB ^ ValueB2).GetHashCode();
}
}
public class NestedC{
public int ValueC;
public int ValueC2;
public override bool Equals(object obj)
{
NestedC other = obj as NestedC;
if (other == null) return false;
return this.ValueC == other.ValueC && this.ValueC2 == other.ValueC2;
}
public override int GetHashCode()
{
return (ValueC ^ ValueC2).GetHashCode();
}
}
After that you can easily select unique Roots (each unique Root represents a group):
roots.Distinct().ToList()
Same result using GoupBy()
:
roots.GroupBy(r => r).Select(g => g.First()).ToList()
Count elements in each group:
roots.GroupBy(r => r).Select(g => g.Count())
Enumerate elements in the first group:
roots.GroupBy(r => r).First().Select(g => g)
If you don't care about elements order in Lists, use Enumerable.All
instead of SequenceEqual
EDIT: Also, in this case you have to change hash code generation alghoritm. For example, like this: hashb = hashb + nb.GetHashCode() * 31;
(additional info about possible algorithms here)
这篇关于C#集团由几个嵌套属性和列表值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!