Foreach loop with dynamic index - c#

In my if-statement i increase the value for counter. I use var counter as the index for subcategories. After the if statement it jumps out from my loop. I would like it to begin looping subcategories[1] or [2] etc. How can i continue looping index 1, 2, 3 for my subcategories list?
int counter = 0;
int eachCounter = 0;
foreach (var item in filteredList[0].subcategories[counter].questionanswer)
{
int questionsCounter = filteredList[0].subcategories[counter].questionanswer.Count;
eachCounter++;
if (eachCounter.Equals(questionsCounter))
{
counter++;
eachCounter = 0;
}
}

Just use a for, since this isn't going to work. The foreach will iterate over the initial questionanswer on the first iteration, it won't go further on the next one.
for (int counter = 0; counter < filteredList[0].subcategories.Count; counter++)
{
var item = filteredList[0].subcategories[counter].questionanswer;
}
If you want to iterate over both lists (the inner and the outer list), use two foreach statements or for loops.

Use for each to loop through filteredList[0].subcategories array this way:
int counter = 0;
int eachCounter = 0;
foreach (var item in filteredList[0].subcategories)
{
// item is filteredList[0].subcategories[0], filteredList[0].subcategories[1] and so on.
int questionsCounter = item.questionanswer.Count;
eachCounter++;
if (eachCounter.Equals(questionsCounter))
{
counter++;
eachCounter = 0;
}
}
I don't know the logic behind your program here, I see you're using counter as a loop variable and changing it in between, so it might not iterate through all elements of filteredList[0].subcategories[] serially. However, if you want to traverse through all elements of filteredList[0].subcategories[] serially using foreach, this is how its done.
Edit:
For traversing through subcategories[0], [1] and so on:
foreach (var item in filteredList[0].subcategories)
{
// item is filteredList[0].subcategories[0], filteredList[0].subcategories[1] and so on.
foreach(element in item)
{
//element is item[0], item[1] and so on i.e
// filteredList[0].subcategories[0].questionAnswer[0]
// filteredList[0].subcategories[0].questionAnswer[1]
// filteredList[0].subcategories[0].questionAnswer[2]
// .
// .
// filteredList[0].subcategories[1].questionAnswer[0]
// filteredList[0].subcategories[1].questionAnswer[1]
// .
// .
}
}

Use a for loop
int eachCounter = 0;
for(int i = 0; i < filteredList[0].subcategories[i].questionanswer.Count; i++)
{
int questionsCounter = filteredList[0].subcategories[i].questionanswer.Count;
eachCounter++; // I am not sure why you are doing this or what the purpose is
if (eachCounter.Equals(questionsCounter))
{
eachCounter = 0;
}
}

Related

Which is the correct method of outputting numbers, based on the count of strings in a list<>

I am trying to loop through a collection, to get the total count of items, and
append the numbers to each item.
So for instance, there is two items in my collection.
#QuizItem.QuitTitle holds two strings, what i am trying to achieve is
Loop through the collecion, outputting the amount of items...
i.e
Music
English
My Code -
#foreach (var QuizItem in QuizDetails)
{
#for (int i = 1; i < indexCount; i++)
{
indexCount = i;
{
<p style="font-weight:bolder">#indexCount #QuizItem.QuizTitle</p>
}
}
And in OnInitialized() method
indexCount = QuizDetails.Count();
The above brings back no results..
If i take out the forloop i get my questions presented.. But obviously the
count is showing 2 on both questions...
Example below
I have tried many of different ways, but to no avail. I just would like for it to say 1 and 2 respectively by the titles, instead of 2 and 2.
Can anybody help?
You should use a foreach loop instead of a for loop, it tends to work much better in Blazor. If you need a counter, a scoped variable that you ++ in the body of the loop will serve
I solved my issue anyway, hopefully it may help, some one in the future.
#foreach (var QuizItem in QuizDetails)
{
#for (int i = 0; i <= indexCount; i++)
{
//indexCount = i;
if (i == 0)
{
i++;
if (temp == 0)
{
temp = i;
}
#for (int b = temp; b <= indexCount; b++ )
{
{
<p style="font-weight:bolder">#b #QuizItem.QuizTitle</p>
if (temp <= indexCount)
{
temp++;
break;
}
}
}
}
}
temp is a int value, that i initialize at 0..

How to optimize code that changes a value deeply nested in an object graph

Below is a crude for-loop to illustrate what I need to do.
Basically, if there are any 'Variable' objects with property 'Name' containing the text "TCC#", then I want to change the 'Type' property (not the .Net type) to 'VariableType.Text'.
The code is going to run over 4800 ParsedCard variables and currently takes a stupid amount of time (about 10 minutes) to simply iterate through the list and write a line to the Debug console.
ParsedCard has
IEnumerable functions which have
IEnumerable groups which have
ParseResults which have
IEnumerable variables
This is such a simple problem but I've tried all sorts of variations using LINQ but can't find anything that performs well (less than 10 seconds).
private void AdjustTCCVariables(IList<ParsedCard> parsedCards)
{
for (var i = 0; i < parsedCards.Count; i++)
{
var parsedCard = parsedCards[i];
for (var j = 0; j < parsedCard.Functions.Count(); j++)
{
var function = parsedCard.Functions.ToList()[j];
for (var k = 0; k < function.Groups.Count(); k++)
{
var group = function.Groups.ToList()[k];
for (var l = 0; l < group.ParseResult.Variables.Count(); l++)
{
var variable = group.ParseResult.Variables.ToList()[l];
if (variable.Name.Contains("TCC#"))
{
//variable.Type = VariableType.Text;
Debug.WriteLine($"Need to change variable at [{i}][{j}][{k}][{l}]");
}
}
}
}
}
}
I've tried with this LINQ but it doesn't actually change the 'variable.Type' of the input list (I suspect because it creates a new copy of the objects in memory and the assignment isn't actually affected the 'parsedCards' IEnumerable at all:
private void AdjustTCCVariables(IEnumerable<ParsedCard> parsedCards)
{
var targetVariables =
parsedCards.SelectMany(x => x.Functions.SelectMany(z => z.Groups))
.SelectMany(x => x.ParseResult.Variables.Where(v => v.Name.Contains("TCC#")));
;
foreach (var variable in targetVariables)
{
variable.Type = VariableType.Text;
}
}
As mentioned, the bottleneck in your iterations is the .ToList() calls.
Since you mention that you only want to edit the variable.Type property, I would solve this like this.
var variables = from parsedCard in parsedCards
from function in parsedCard.Functions
from group in function.Groups
from variable in group.ParseResult.Variables
where variable.Name.Contains("TCC#")
select variable;
foreach (var variable in variables) {
variable.Type = VariableType.Text;
}
You don't need to know anything other than the variable objects that need changing, you don't need all the indexes and all the other variables. Just select what you need to know, and change it.
This way you will not know the indexes, so your Debug.WriteLine(...); line won't work.
Without knowing what the defintion of the classes , here is some tips.
Remove toList, dont count on the iteration (for statement)
int numberOf = parsedCards.Count
for (var i = 0; i < numberOf; i++)
{
//var parsedCard = parsedCards[i];
int noOf2 = parsedCard[i].Functions.Count()
for (var j = 0; j < noOf2; j++)
{
var function = parsedCard[i].Functions[j];
int = function.Groups.Count();
for (var k = 0; k < noOfGroups; k++)
{
var group = function.Groups[k];
int noOfVars = group.ParseResult.Variables.Count();
for (var l = 0; l < noOfVars; l++)
{
var variable = group.ParseResult.Variables[l];
if (variable.Name.Contains("TCC#"))
{
//variable.Type = VariableType.Text;
Debug.WriteLine($"Need to change variable at [{i}][{j}][{k}][{l}]");
}
}
}
}
}

Keep last N items and remove other items from ListBox

I have a C# Winform with a ListBox. I am trying to remove all the items except the last 5 items. The ListBox sort is set to Ascending.
The items in the ListBox look like the following:
2016-3-1
2016-3-2
2016-3-3
2016-3-4
...
2016-03-28
Here is my code to remove the beginning items.
for (int i = 0; i < HomeTeamListBox.Items.Count - 5; i++)
{
try
{
HomeTeamListBox.Items.RemoveAt(i);
}
catch { }
}
I've also tried HomeTeamListBox.Items.RemoveAt(HomeTeamListBox.Items[i]);
While there are more than n items in the list, you should remove items from start of the list.
This way you can keep the last n items of ListBox:
var n = 5;
while (listBox1.Items.Count > n)
{
listBox1.Items.RemoveAt(0);
}
Your index i is going to increase by one each time it loops, but you are going to be removing an element each time you loop. What you want to do is remove each element at index 0 for the first 5 passes. So using your current For Loop
HomeTeamListBox.Items.RemoveAt(HomeTeamListBox.Items[0]);
Is what you want in the body.
This should work for you;
if(HomeTeamListBox.Items.Count > 5)
{
var lastIndex = HomeTeamListBox.Items.Count - 5;
for(int i=0; i < lastIndex; i++)
{
HomeTeamListBox.Items.RemoveAt(i);
}
}
for(int i = HomeTeamListBox.Items.Count-5; i>=0; i--)
{
HomeTeamListBox.Items.RemoveAt(i);
}

listboxes passing values from each other

I'm trying to multiply the values of 2 listboxes together and make their product appear at another list box I'm getting the results I need but the problem is when I rerun the loop using a command button the listbox removes the next instance of the first value calculated by ppc[i] * qty[i] but when I try to remove the the listBox4.Items.Remove(ppc[i] * qty[i]) it reprints the whole array again from first element to last element
string myString = textBox1.Text.ToString();
int index = listBox6.FindString(myString, -1);
int[] qty = new int[99];
int[] ppc = new int[99];
int[] gt1 = new int[99];
listBox3.Items.Add(listBox5.Items[index]);
listBox1.Items.Add(textBox2.Text.ToString());
if (index != -1)
{
listBox6.SetSelected(index, true);
listBox2.Items.Add(textBox1.Text); //name
}
listBox3.Items.Add(listBox5.Items[index]);
listBox3.Items.Remove(listBox5.Items[index]);
for (int i = 0; i != listBox2.Items.Count ; i++)
{
ppc[i] = Convert.ToInt32(listBox3.Items[i]);
qty[i] = Convert.ToInt32(listBox1.Items[i]);
listBox4.Items.Remove(ppc[i] * qty[i]);
listBox4.Items.Add((ppc[i] * qty[i]));
}
My understanding is that this loop works once, and then when it is re-run it is out of order. Are you making sure to clear listbox4 each time this loop is executed? Also since listBox2 isn't used, it is probably better not to use it for your loop bounds.
if(listBox1.Items.Count == listBox3.Items.Count)
{
int rowCount = listBox1.Items.Count;
listBox4.Items.Clear();
for (int i=0; i < rowCount; i++)
{
ppc[i] = Convert.ToInt32(listBox3.Items[i]);
qty[i] = Convert.ToInt32(listBox1.Items[i]);
listBox4.Items.Insert(i , (ppc[i] * qty[i]));
}
}

Do something for every hundredth element in an array

I have 1 million elements in an array, I need to divide these elements into groups of 100, do a function and continue working on the next hundred
foreach (string value in lines)
{
filescreated++;
if (filescreated == ?????????)
{
do stuff
}
}
???? is equal to value divisible by 100
is equal to value divisable by 100
foreach (...)
{
filescreated++;
if (filescreated % 100 == 0)
{
// do stuff for the every 100th element
}
// do other stuff for every element
}
Reference: modulus (%) operator
Use this if you need to do something special for every 100th element, but you still need to process every element.
If you only need to process every 100th element, refer to Reed's answer.
What about this (if you need in order and % isn't good for you)?
The question is confusing as you talk about every hundredth element, then after about packs of 100. So here would be a guess.
string[] lines = new string[1000000];
for (int i = 0; i < 10000; i++)
{
for (int j = 0; j < 100; j++)
{
DoSomething(lines[100*i + j], i);
}
}
I need to divide these elements into groups of 100, do a function and continue working on the next hundred
You can do this directly, if this is an array, just by using a for loop and incrementing by 100:
int chunkSize = 100;
for (int start=0; start<lines.Length;start += chunkSize)
{
ProcessSectionOfArray(lines, start, Math.Min(start+chunkSize-1, lines.Length-1));
}
Here is a solution which separates the partitioning logic into a separate function.
// A separate static function
private static IEnumerable<IEnumerable<T>> BreakIntoBlocks<T>(T[] source, int blockSize)
{
for (int i = 0; i < source.Length; i += blockSize)
{
yield return source.Skip(i).Take(blockSize);
}
}
// And in your code
string[] lines = new string[1000000];
foreach(IEnumerable<string> stringBlock in BreakIntoBlocks(lines, 100))
{
// stringblock is a block of 100 elements
// Here is where you put the code that processes each separate group
}
The attempt above should be faster than my first attempt (below)
int blockSize = 100;
int i = 0;
IEnumerable<IEnumerable<string>> query = from s in lines
let num = i++
group s by num / blockSize into g
select g;
foreach(IEnumerable<string> stringBlock in query)
{
// Stringblock will be a block of 100 elements.
// Process this 100 elements here.
}
The problem which using the grouping clause is that LINQ will allocate every one of those 1000000 element to groups before it returns the first element.

Categories