- Home /
Looping list information into another list
I'm trying to create a menu that shows a certain amount of levels per page, (so more than 6 levels will add another page).
But my pages.levels list is showing the "Level 01" 6 times in both page lists, where it should be the first 6 levels in the first and only level 07 in the second (I'm using 7 strings as 'levels' currently)
PagesHandler.cs public class PageHandler { public int index; public List pages; }
Page.cs' public class Page { public List levels; }
This is my MainMenu.CS
public List<string> levels;
public PageHandler pageHandler;
int pageCount = 1;
int count = 0;
void Start () {
//Check How Many Pages Needed
for (int i = 0; i < levels.Count; i++) {
if (count == 5) {
pageCount++;
count = 0;
} else {
count++;
}
}
//Set Page Handler
pageHandler = new PageHandler ();
pageHandler.pages = new List<Page>(pageCount);
for (int j = 0; j < pageCount; j++)
{
pageHandler.pages.Add(new Page());
pageHandler.pages[j].levels = new List<string>();
}
//Add levels to page
for (int k = 0; k < levels.Count; k++)
{
for (int l = 0; l < pageHandler.pages.Count;)
{
if(pageHandler.pages[l].levels.Count == 6)
{
l++;
} else {
pageHandler.pages[l].levels.Add(levels[k]);
}
}
}
}
Thanks!
Answer by richyrich · Nov 27, 2014 at 08:50 PM
Hi. Unfortunately, your page counting fails on several points. In these situations, it is often a good idea to revert to pen and paper to consider why it does not work. Let's look at your 'Check How Many Pages Needed' loop. In the first column we write the index, in the second we write what the value of count is when we check it and finally we write the value at the end of that particular cycle (iteration) of the loop...
Index Check Count
0 0 1
1 1 2
2 2 3
3 3 4
4 4 5
5 5 0 //This is due to the else (we should actually increment regardless)
6 0 1
So by the end of the loop, we have an error in that we've lost an entry
Later on in the program, we ignore the fact that count now is equal to one. We should have added an if-statement at the end saying that is count>0, pageCount++; However, you're checking for == 5, but elsewhere you have stated that you want 6 entries to a page, so you have another error of logic there. Sorry.
Here's the light at the end of the tunnel though... you don't even need the loop ;)
Instead, you need to use the modulus operator (%). This works like division, only it tells you the remainder of a division.
So for example 9/4 = 1 (9/4 [using whole values == 2], but the remainder is 1
So in your context, we can change your for loop to:
int entriesPerPage = 6;
int rem = levels.Count% entriesPerPage;
pageCount = (levels.Count- rem) / entriesPerPage;
if (rem > 0)
pageCount++;
Part II!
Try to avoid nested loops if you can, they can make debugging more difficult. This next piece of code I've not spent too much time on, so have a play first. Any problems, just add a comment and let us know :D
int nextlevels = entriesPerPage;
int currentPage = 0;
for(int i=0;i<levels.Count;i=i+entriesPerPage)
{
if (nextlevels > (levels.Count - 1)) //might not need -1, brain index failure ;)
{
nextlevels = levels.Count - 1;
pageHandler.pages[currentPage].levels = levels.GetRange(i, nextlevels);
break;
}
else
{
pageHandler.pages[currentPage].levels = levels.GetRange(i, nextlevels);
}
nextlevels += 6;
}
Cheers for the great reply! (I'd upvote you too but unfortunately I don't have the 'reputation' yet)
I've never thought to write down iterations like that, looks very useful, i'll be doing that a lot from now on!
The 5 at the start and the 6 later on was just a preference change, that I embarrassingly forgot to fix!
That modulus operator section looks brilliant as well, a lot less messy too! Just overall a great reply !
Thank you I've learned a lot!
Glad I was able to help.
The 5 at the start and the 6 later on was just a preference change
Problems like these can be avoided using named values; the code above uses int entriesPerPage = 6; Note: the last line of code (nextlevels += 6;) should have been nextlevels += entriesPerPage;
Named values improve readability and reduce bug opportunities. This can further be improved by not allowing it to be changed. You could declare it as a constant at the top of the class as: public const int EntriesPerPage = 6; Now the only place to change would be at declaration.
Thanks again for the response and the good advice!
Sorry for being 'that guy', but I'm getting an error with this, I thought I understood it seems I don't.
I'm getting this error: ArgumentException: index and count exceed length of list
$$anonymous$$y gut feeling is that it's the 'i' on the second iteration being 12? Hard to know cause i'm always having brain index failure!
Using int nextlevels = entriesPerPage; int currPage = 0;
for(int i = 0; i < levels.Count; i += entriesPerPage)
{
if (nextlevels > levels.Count)
{
nextlevels = levels.Count - 1;
pageHandler.pages[currPage].levels = levels.GetRange(i, nextlevels);
break;
} else {
pageHandler.pages[currPage].levels = levels.GetRange(i, nextlevels);
}
currPage++;
nextlevels += 6;
}
You are just exceeding the number of elements inside the levels List. I won't be able to do anything more until tomorrow. But message received, will look at it again unless you fix it in meantime.
You're not 'that guy'! Chill, it'll get fixed :D
Try this:
int nextlevels = 6;
for(int i = 0;i < levels.Count;i=i + 6)
{
if (i+nextlevels >= levels.Count)
{
nextlevels = levels.Count - i;
pageHandler.pages[currPage].levels = levels.GetRange(i, nextlevels);
break;
}
else
{
pageHandler.pages[currPage].levels = levels.GetRange(i, nextlevels);
}
currPage++;
}
Your answer
