C# - 递归访问 List<> 的子部分
本文关键字:递归 访问 List | 更新日期: 2023-09-27 18:25:28
我正在开发一个作为停车场模拟器运行的程序。为此,我有:
一个名为ParkingSpace
的类
一个List<ParkingSpace>
名为 Level
的类(包含 List<ParkingSpace>
作为属性(
一个List<Level>
List<ParkingSpace>
列表中的空格数由用户输入决定。将所有ParkingSpace
实例添加到列表中后,我想将它们均匀地分布在级别数中(即,如果有 30 个空格和 3 个级别,则在每个Level
实例的 List<ParkingSpace>
属性中添加 10 个空格。
考虑到这个例子,我试图将前 10 个空格放入第一级,中间 10 个空格进入第二级,最后 10 个空格进入第三级。我尝试使用 for
循环和 List<ParkingSpace>.getRange()
方法执行此操作,如下所示:
//number of spaces to be set on each level
//total spaces divided by levels to be spread across
int spacesPerLevel = spaces.Count / numLevels;
//for as many levels as there are
for (int i = 0; i < numLevels; i++)
{
//level at index holds range
//level index multiplied by number of spaces on any one level
int listRangeStart = (i * spacesPerLevel);
//create sub-collection of spaces to be applied to level
ParkingSpaces subSpaces = spaces.getRange(listRangeStart, spacesPerLevel);
//add these spaces to level
Level level = new Level(subSpaces);
//add created level to collection of levels
Add(level);
//remove these spaces from ParkingSpaces collection once applied to level
//try to prevent loose collection of spaces not applied to levels
spaces.RemoveRange(listRangeStart, spacesPerLevel);
}
我本以为这会很好用,但由于某种原因,我继续对getRange()
方法进行OutOfRangeException
。
我已经对算法进行了数学计算,据我所知,它应该可以工作。任何人都可以在这里发现任何可能抛弃它的问题吗?或者,有没有更简单的方法可以递归地将主列表的子集添加到另一个列表?
这是因为调用RemoveRange
,从而减小了列表的大小,从而减少了错误。要解决此问题,只需将带有.GetRange
的行更改为:
ParkingSpaces subSpaces = spaces.GetRange(0, spacesPerLevel);
而你打电话的那行RemoveRange
这个:
spaces.RemoveRange(0, spacesPerLevel);
或者,有没有更简单的方法可以递归地将主列表的子集添加到另一个列表?
好吧,无论如何,您的代码中实际上不涉及任何递归,但这里有一个简单的方法:
for(int i=0;i<numLevels;i++)
{
var skip =i*spacesPerLevel;
var subSpaces = spaces.Skip(start).Take(spacesPerLevel);
var level = new Level(subSpaces);
Add(level);
}
实际上,您正在创建的是一种分页算法,并且由于您使用的是实现IEnumerable<T>
的List<T>
,因此可以利用 Skip 和 Take 方法。
也许你可以尝试 LINQ 方法:
var count = 0;
var spacesPerLevel = spaces.Count / numLevels;
var levels = spaces
.GroupBy(t => count++ / spacesPerLevel)
.Select(t => new Level(new ParkingSpaces(t.ToList())))
.ToList();
AddRange(levels);
当然,需要注意的事情很少。Level
构造函数必须将ParkingSpaces
作为参数,ParkingSpaces
类构造函数必须将 en IEnumerable<ParkingSpace>
作为参数。LINQ 表达式将返回 List<Level>
,您可以在AddRange
方法中使用它一次添加所有级别。
您正在从集合中删除空格,因此您无法获得所需的范围,因为该范围不再存在,我建议使用队列而不是列表,在达到每个级别的最大数量时取消元素排队。
也将是一个很好的练习。
foreach (var level in levels) {
while(spaces.any() && level.spaces.count() <= maxPerLevel) {
level.spaces.add (spaces.dequeue());
}
}
您还应该考虑不要均匀划分数字,如果有人输入 3 个级别和 11 个空格怎么办?