I am little bit confused about loops in C#, What is best use cases for various loops like For, foreach, while, do while, List.ForEach?
Depends on the usecase. For example, if you want only the odd indexed items in an array, use a for loop with +2 in each run. ForEach is suitable for standard loops. But in some cases you cannot use one of them, e.g. in a foreach you cannot delete items from the collection. You need e.g. for in this case.
And, when you have a specific condition, you need a while loop.
You use for loop when you wanted to set a counter iteration such
for(int i=0;i<3;i++)//will loop until it meets the condition i<3
{ //statement here}
You use foreach if you are going to loop and display the collection of a variable such
string[] name = { "josh", "aj", "beard" };
// ... Loop with the foreach keyword.
foreach (string value in name)
{
Console.WriteLine(name);
}
while is use if you want to meet the condition first before the statement
while(condition)
{
//statement here
}
do while is use if you want to do the statement first before the condition
do
{
//statement here
}
while(condition)
Related
I have a loop that is going through each element of a list.
At the moment I have the foreach loop, and inisde, an if that check a variable for the element of the list. If the value is true, I do certain activities, otherwise I move on.
I was wondering if there is some sort of construct, that would allow me to write something like
foreach (myclass item in itemlist) where ( item.is_red)
{
... do something
}
instead than what I have currently
foreach (myclass item in itemlist)
{
if (item.is_red)
... do something
}
From what I recall, the "where" can be used only as constant definition mechanism, like when defining a specific type of class; so it can't be used in the context that I am presenting here. Am I stuck with the if-else inside the loop as only solution?
Convert the enumeration to List and use the Where and ForEach LINQ operator:
itemlist.Where(t => t.is_red).ToList().ForEach(t => DoSomething(t));
or
itemlist.Where(t => t.is_red).ToList().ForEach(t =>
{
// do something
}
You could use LINQ
foreach (myclass item in itemlist.Where(i => i.is_red))
{
//... do something
}
Yes, you could filter what you want iterate with LINQ Where in the collection first:
foreach (myclass item in itemlist.Where(x => x.is_red)) //here is the `Where`
{
//do your stuffs
}
Almost :)
foreach (var item in (from i in numbers where i.is_red select i))
{
... do something
}
There generally is a small performance hit when LINQ is used to iterate over lists or arrays, since an enumerator object is to be created.
Another way to tackle your problem is to use your condition as guard clause. This can reduce nesting and complexity and usually improves readability (although there is also the opinion of not using multiple returns/continues/breaks in a function/loop to keep cyclomatic complexity down):
foreach (var item in itemlist)
{
if (!item.is_red) { continue; }
... do something
}
In the end it probably boils down to company policy/personal preference.
I have the following piece of code which uses the foreach iterator.
foreach (var item in daysOfWeeksList)
{
daysOper |= item;
}
daysOfWeeksList is a list. I want to OR each item in the list and process the result?
This daysOfWeeksList is a
List<int> daysOfWeeksList
Say I wan to do something like this. The dosomething I want to do is the OR operation.
list.ForEach( item =>
{
item.DoSomething();
} );
How would you go about this using an foreach method available as part of the List collection? I got plenty of examples for this for 2 operands but not for a single operand.
Assuming daysOper starts as 0, I wouldn't use ForEach at all - I'd use Aggregate from LINQ:
var daysOper = daysOfWeekList.Aggregate((current, next) => current | next);
In other words, keep a running "current" value, and keep OR-ing it with the next value each time. (The result of one iteration will be used as the "current" value for the next iteration.)
In general, you want to use the Aggregate method for stuff like this where the standard aggragetors, like Sum don't fit.
(Edit: I assumed that the OP was doing the OR operation over a List. So I edited the below paragraph)
However, if DaysOfWeekList is a List, then have the opportunity to optimize performance by stopping at the first instance of "true". The Any method does this.
var result = daysOfWeekList.Any(daysOpr=>daysOpr);
Look at this csharp code, and see if you can tell why I need to exit the loop after I found and deleted an item from the list. The idea is to go through a node's list of neighbors, and see if a Node n exists there, then delete that neighbor:
internal void RemoveDirected(Node n)
{
foreach (EdgeToNeighbor etn in this.Neighbors)
{
if (etn.Neighbor.Key == n.Key)
{
RemoveDirected(etn);
break;
}
}
}
internal void RemoveDirected(EdgeToNeighbor e)
{
Neighbors.Remove(e);
}
.
.
.
// Removes EdgeToNeighbor instance from AdjacencyList
protected internal virtual void Remove(EdgeToNeighbor e)
{
base.InnerList.Remove(e);
}
Notice how I have a "break" after the RemoveDirected call in the first method.
I've found that if I didn't exit after the RemoveDirected
it would go on forever in the foreach loop. I suppose it must have
something to do with the way foreach works. If you modify the list
that foreach is working on, it gets confuse and loops forever.
Have you seen this type of thing, and what are other options to use rather than using break?
Of course, I could place the node that I've found in a local variable, then break from the loop, and
delete it outside of the loop. But I was thinking, may be there are better ways to do this
in csharp.
When you iterate a .NET collection using its iterator, you must not modify that collection. If you do, you are asking for trouble.
You should defer the deletion instead of deleting right in the foreach loop. For example, you can collect everything you need to delete in a list, and then delete it outside of foreach.
var toDelete = this.Neighbors.Where(etn => etn.Neighbor.Key == n.Key).ToList();
foreach (var e in toDelete) {
Neighbors.Remove(e);
}
You definitely don't want to use an iterator if you are removing items. One option is to change it to downward counting loop:
for (int nI = this.Neighbors.Count; nI >= 0; nI--)
{
var etn = this.Neighbors[nI];
if (etn.Neighbor.Key == n.Key)
{
RemoveDirected(n);
}
}
You could also collect the keys or items to be deleted in a collection within the loop and then perform the deletion once you have completed your iteration.
However, if you are only removing a single item and the items in the collection are keyed somehow, then you shouldn't actually need any loop. Just test the existence of the key or item in the collection and, if it is there, just remove it.
You could get the number of nodes and then check and delete from highest to lowest in a for loop that way you avoid looking for an item that no longer exists.
Since ForEach() method loop through all list members, Why can't I use a break/continue clause while I can use them inside a normal foreach loop
lstTemp.ForEach(i=>
{
if (i == 3)
break;
//do sth
}
);
Error:
"No enclosing loop out of which to
break or continue"
Because ForEach is a method and not a regular foreach loop. The ForEach method is there for simple tasks, if you need to break or continue just iterate over lstTemp with a regular foreach loop.
Usually, ForEach is implemented like this:
public static ForEach<T>(this IEnumerable<T> input, Action<T> action)
{
foreach(var i in input)
action(i);
}
As it is a normal method call, action doesn't know anything about the enclosing foreach, thus you can't break.
return will act as continue in ForEach.
Example:
var list = new List<int>() {1, 2, 3, 4};
list.ForEach(i =>
{
if (i == 3)
return;
Console.WriteLine(i);
}
);
Prints 1, 2, 4.
3 - skipped.
Presumably because you're using a lambda and the contents of the lambda are ignorant to the fact that it's being used inside a loop.
rather than using a break, perform a filter first like this (it may not be the exact filter you need, but illustrates the point)
lstTemp.Where(i => i!= 3).ForEach(i=> // do sth);
The way I'd explain it is this: ForEach is a method, not a language feature. The C# foreach construct is a feature of the language within which the other language constructs break and continue are permitted.
I would also point out (not trying to judge, just making an observation) that this is a good example of why some developers object to the use of a ForEach method: it doesn't really save typing in this simple case, it requires one more redirection than necessary, and it doesn't have all the functionality of foreach anyway.
In my opinion the main scenario in which a ForEach method makes sense is as an extension on IEnumerable<T>--to put at the end of a chain of method calls. It seems (to me) a bit strange that they added it to List<T>.
To iterate only part of the items and emulate the break perfectly, you can use FirstOrDefault:
lstTemp.FirstOrDefault(i=>
{
if (i == 3)
return true;
//do stuff
return false;
}
);
For list with 100000 items, if the 10th item is 3 it will iterate only 10 times, using the Where solution will work, but iterate the whole list first.
Because ForEach is a method and not a regular foreach loop is need iterate over lstTemp with a regular foreach loop in case break, but in case continue use return inside the ForEach method.
var lstTemp = new List<int>() {1, 2, 3, 4};
lstTemp.ForEach(i=>
{
if (i == 3) return;
//do sth
Console.WriteLine(i);
});
Output: 1, 2, 4
break and continue are C# language keywords that require compiler support. ForEach, to the C# compiler, is just a method.
Because you delegate an action for each item in the list.
i used it
list.ForEach((item) =>
{
if( isBreak == false ) do
{
if (isContinue)
break;
// TODO
} while (false); }
});
I have a loop that iterates through elements in a list. I am required to remove elements from this list within the loop based on certain conditions. When I try to do this in C#, I get an exception. apparently, it is not allowed to remove elements from the list which is being iterated through. The problem was observed with a foreach loop. Is there any standard way to get around this problem?
Note : One solution I could think of is to create a copy of the list solely for iteration purpose and to remove elements from the original list within the loop. I am looking for a better way of dealing with this.
When using List<T> the ToArray() method helps in this scenario vastly:
List<MyClass> items = new List<MyClass>();
foreach (MyClass item in items.ToArray())
{
if (/* condition */) items.Remove(item);
}
The alternative is to use a for loop instead of a foreach, but then you have to decrement the index variable whenever you remove an element i.e.
List<MyClass> items = new List<MyClass>();
for (int i = 0; i < items.Count; i++)
{
if (/* condition */)
{
items.RemoveAt(i);
i--;
}
}
If your list is an actual List<T> then you can use the built-in RemoveAll method to delete items based on a predicate:
int numberOfItemsRemoved = yourList.RemoveAll(x => ShouldThisItemBeDeleted(x));
You could use LINQ to replace the initial list by a new list by filtering out items:
IEnumerable<Foo> initialList = FetchList();
initialList = initialList.Where(x => SomeFilteringConditionOnElement(x));
// Now initialList will be filtered according to the condition
// The filtered elements will be subject to garbage collection
This way you don't have to worry about loops.
You can use integer indexing to remove items:
List<int> xs = new List<int> { 1, 2, 3, 4 };
for (int i = 0; i < xs.Count; ++i)
{
// Remove even numbers.
if (xs[i] % 2 == 0)
{
xs.RemoveAt(i);
--i;
}
}
This can be weird to read and tough to maintain, though, especially if the logic in the loop gets any more complex.
Another trick is to loop through the list backwards.. removing an item won't affect any of the items you are going to encounter in the rest of the loop.
I'm not recommending this or anything else though. Everything you need this for can probably be done using LINQ statements to filter the list on your requirements.
You can iterate with foreach this way:
List<Customer> custList = Customer.Populate();
foreach (var cust in custList.ToList())
{
custList.Remove(cust);
}
Note: ToList on the list of variables, this iterates through the list created by the ToList but removes the items from the original list.
Hope this helps.
The recommended solution is to put all your elements you want to remove in a separate list and after the first loop, put a second loop where you iterate over the remove-list and remove those elements form the first list.
The reason you get an error is because you're using a foreach loop. If you think about how a foreach loop works this makes sense. The foreach loop calls the GetEnumerator method on the List. If you where to change the number of elements in the List, the Enumerator the foreach loop holds wouldn't have the correct number of elements. If you removed an element a null exception error would be thrown, and if you added an element the loop would miss an item.
If you like Linq and Lamda expressions I would recommend Darin Dimitrov solution, otherwise I would use the solution provided by Chris Schmich.