【发布时间】:2019-10-25 18:56:21
【问题描述】:
所以最近我遇到了一个问题,我和我的团队需要获取一个对象列表,并按条件分组,然后按更多条件分组,然后按更多条件分组,以此类推 7 或所以水平。经过几天的思考,我终于想出了一种树状结构,尽管每个级别都是手动定义的(主要是为了便于阅读,因为一旦编程它就会一成不变)。处理此问题的最佳方法是什么,如果可能,为什么? 到目前为止,这是我使用随机整数列表的结果。检查是:可被 2 整除、被 3 整除和被 5 整除的顺序(尽管条件的顺序与要求无关):
这是整数随机列表加上 TopNode 类的代码
Random rand = new Random();
List<int> ints = new List<int>();
for (int i = 0; i < 10; i++)
{
ints.Add(rand.Next(0, 10000001));
}
TopNode node = new TopNode(ints);
这是顶层节点类的其余代码
public class TopNode
{
public Even Even { get; set; }
public Odd Odd { get; set; }
public TopNode(List<int> ints)
{
var even = ints.Where(x => x % 2 == 0).ToList();
var odd = ints.Where(x => x % 2 != 0).ToList();
if (even.Count > 0)
{
Even = new Even(even);
}
if (odd.Count > 0)
{
Odd = new Odd(odd);
}
}
}
public class Even {
public Mulitple3 Mulitple3 { get; set; }
public NotMulitple3 NotMulitple3 { get; set; }
public Even(List<int> ints)
{
var multiple = ints.Where(x => x % 3 == 0).ToList();
var not = ints.Where(x => x % 3 != 0).ToList();
if (multiple.Count > 0)
{
Mulitple3 = new Mulitple3(multiple);
}
if (not.Count > 0)
{
NotMulitple3 = new NotMulitple3(not);
}
}
}
public class Odd {
public Mulitple3 Mulitple3 { get; set; }
public NotMulitple3 NotMulitple3 { get; set; }
public Odd(List<int> ints)
{
var multiple = ints.Where(x => x % 3 == 0).ToList();
var not = ints.Where(x => x % 3 != 0).ToList();
if (multiple.Count > 0)
{
Mulitple3 = new Mulitple3(multiple);
}
if (not.Count > 0)
{
NotMulitple3 = new NotMulitple3(not);
}
}
}
public class Mulitple3
{
public Multiple5 Multiple5 { get; set; }
public NotMultiple5 NotMultiple5 { get; set; }
public Mulitple3(List<int> ints)
{
var multiple = ints.Where(x => x % 5 == 0).ToList();
var not = ints.Where(x => x % 5 != 0).ToList();
if (multiple.Count > 0)
{
Multiple5 = new Multiple5(multiple);
}
if (not.Count > 0)
{
NotMultiple5 = new NotMultiple5(not);
}
}
}
public class NotMulitple3
{
public Multiple5 Multiple5 { get; set; }
public NotMultiple5 NotMultiple5 { get; set; }
public NotMulitple3(List<int> ints)
{
var multiple = ints.Where(x => x % 5 == 0).ToList();
var not = ints.Where(x => x % 5 != 0).ToList();
if (multiple.Count > 0)
{
Multiple5 = new Multiple5(multiple);
}
if (not.Count > 0)
{
NotMultiple5 = new NotMultiple5(not);
}
}
}
public class Multiple5
{
public List<int> ints { get; set; }
public Multiple5(List<int> ints)
{
this.ints = ints;
}
}
public class NotMultiple5
{
public List<int> ints { get; set; }
public NotMultiple5(List<int> ints)
{
this.ints = ints;
}
}
【问题讨论】:
-
在树中拥有单独的子组而不只是对象上的属性的目的是什么?
-
@Madmmoore,对我来说看起来不错。由于一切都是通过构造函数初始化的,所以我会将数据结构设为只读:使用
{get;}属性而不是{get;set;},以及public IReadOnlyList<int> ints而不是public List<int> ints。 -
除非您拥有数百万个对象,否则“最佳”方式可能只是
List<T>并使用 LINQGroupBy对它们进行分组。这是最容易编写、最容易理解、最容易处理不断变化的需求,可以处理内存中的大型集合,并且可以在需要时转换为数据库查询。永远不要低估优化代码扫描对简单数据结构的蛮力速度与围绕一些“聪明”指针网络进行内存跳跃的蛮力速度。 -
@KyleW 因为每个组都需要是其上一个组的一组。所以 {1,2,3,4,5,6,7,8} -> {1,2,3,4} -> {1,3} {2,4} 和 {5,6,7,8 } -> {5,7} {6,8} 等等。我试图想出一种方法来使用属性来做到这一点,但我所有的解决方案最终都会一遍又一遍地进行相同的计算,并且很快就变得非常笨拙
-
如果我们能看到更接近实际需要的东西可能会有所帮助。使用 LINQ 执行
ints.Where(i => i.IsEven).Where(i => i.IsAMultipleOf3)非常容易使用、修改和理解。如果我们更好地理解您的用例,那么为您推荐更好的东西会更容易。这也很容易摆脱层次结构,所以我很难了解层次结构的目的是什么。
标签: c# linq data-structures