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

我已经对算法进行了数学计算,据我所知,它应该可以工作。任何人都可以在这里发现任何可能抛弃它的问题吗?或者,有没有更简单的方法可以递归地将主列表的子集添加到另一个列表?

C# - 递归访问 List<> 的子部分

我认为

这是因为调用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 个空格怎么办?