Reputation: 596
I'm working on a program that operates as a Car Park simulator. To do this, I have:
A class called ParkingSpace
A List<ParkingSpace>
A class called Level
(contains List<ParkingSpace>
as an attribute)
A List<Level>
The number of spaces in the List<ParkingSpace>
list is decided via user input. Once all of the ParkingSpace
instances have been added to the list, I would like to spread them evenly across the number of levels (i.e. if there are 30 spaces and 3 levels, 10 spaces are added to the List<ParkingSpace>
attribute of each Level
instance.
With this example in mind, I have tried to get the first 10 spaces into the first level, the middle 10 spaces into the second level, and the last 10 spaces into the third level.
I have tried to carry this out using a for
loop, and the List<ParkingSpace>.getRange()
method, as shown below:
//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);
}
I'd have thought this would have worked fine, but for some reason I continue to get an OutOfRangeException
on the getRange()
method.
I've done the maths on the algorithm and it should work as far as I know. Can anyone spot any problems here that might be throwing it off? Alternatively, is there a simpler way to go about adding a subset of the main list another list recursively?
Upvotes: 0
Views: 208
Reputation: 7505
Alternatively, is there a simpler way to go about adding a subset of the main list another list recursively?
Well there isn't really any recursion involved in your code anyway, but here is a simple way to so it:
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);
}
Effectively what you're creating is a paging algorithm, and since you're using List<T>
, which implements IEnumerable<T>
, you can take advantage of the Skip and Take methods.
Upvotes: 2
Reputation: 1620
You are removing the spaces from the collection, so you can't get the range you want because that range does not exist anymore, i suggest to use a queue instead of a list, dequeue the elements while you reach the maximum amount per level.
Will be a good exercise too.
foreach (var level in levels) {
while(spaces.any() && level.spaces.count() <= maxPerLevel) {
level.spaces.add (spaces.dequeue());
}
}
You should also think to not evenly divisibile numbers, what if someone input 3 levels and 11 spaces?
Upvotes: 0
Reputation: 1176
Maybe you could try LINQ approach:
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);
Of course, there are few things to be aware of. Your Level
constructor must take ParkingSpaces
as an argument and your ParkingSpaces
class constructor must take en IEnumerable<ParkingSpace>
as an argument.
LINQ expression will return List<Level>
, which you can use in AddRange
method for adding all levels at once.
Upvotes: 0
Reputation: 113
I think it's because of the RemoveRange
call, thus decreasing the size of the list, thus the error. To fix this simply change the line with .GetRange
to this:
ParkingSpaces subSpaces = spaces.GetRange(0, spacesPerLevel);
And the line where you call RemoveRange
to this:
spaces.RemoveRange(0, spacesPerLevel);
Upvotes: 2