Define a condition in a loop, without add an if - c#

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.

Related

How to reduce multiple nested foreach blocks

I have the following scenario:
var Ids = object1.GetIds(); // returns IEnumerable<int>
foreach (var id in Ids)
{
foreach (var relatedObject in object1.GetRelatedObjects(id))
{
// Do Something with related object
}
}
In this case, i want to get rid of from the first foreach and reduce this logic into single foreach. How could i achieve this?
Should it be possible with LINQ expression some similar methodology?
When there is nothing between the two loops, before or after the nested one, you can use SelectMany to "flatten" two loops into one:
foreach (var relatedObject in Ids.SelectMany(object1.GetRelatedObjects)) {
...
}
One major difference between this loop and the loop that you have is that id is no longer in scope. Assuming that relatedObject exposes a public Id property, this should not be a problem in your situation, because you could extract the id back with
var id = relatedObject.Id;
Personally I like to take full advantage of the optional braces/block for foreach loops.
You can't reduce the complexity. But you can make it look nicer
IEnumerable<int> Ids = object1.GetIds()
foreach (var id in Ids)
foreach (var relatedObject in object1.GetRelatedObjects(id))
{
DoSomething(relatedObject);
}

C# various type loop usage

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)

How add or remove object while iterating Collection in C#

I am trying to remove object while I am iterating through Collection. But I am getting exception. How can I achieve this?
Here is my code :
foreach (var gem in gems)
{
gem.Value.Update(gameTime);
if (gem.Value.BoundingCircle.Intersects(Player.BoundingRectangle))
{
gems.Remove(gem.Key); // I can't do this here, then How can I do?
OnGemCollected(gem.Value, Player);
}
}
foreach is designed for iterating over a collection without modifing it.
To remove items from a collection while iterating over it use a for loop from the end to the start of it.
for(int i = gems.Count - 1; i >=0 ; i--)
{
gems[i].Value.Update(gameTime);
if (gems[i].Value.BoundingCircle.Intersects(Player.BoundingRectangle))
{
Gem gem = gems[i];
gems.RemoveAt(i); // Assuming it's a List<Gem>
OnGemCollected(gem.Value, Player);
}
}
If it's a dictionary<string, Gem> for example, you could iterate like this:
foreach(string s in gems.Keys.ToList())
{
if(gems[s].BoundingCircle.Intersects(Player.BoundingRectangle))
{
gems.Remove(s);
}
}
The easiest way is to do what #IV4 suggested:
foreach (var gem in gems.ToList())
The ToList() will convert the Dictionary to a list of KeyValuePair, so it will work fine.
The only time you wouldn't want to do it that way is if you have a big dictionary from which you are only removing relatively few items and you want to reduce memory use.
Only in that case would you want to use one of the following approaches:
Make a list of the keys as you find them, then have a separate loop to remove the items:
List<KeyType> keysToRemove = new List<KeyType>();
foreach (var gem in gems)
{
gem.Value.Update(gameTime);
if (gem.Value.BoundingCircle.Intersects(Player.BoundingRectangle))
{
OnGemCollected(gem.Value, Player);
keysToRemove.Add(gem.Key);
}
}
foreach (var key in keysToRemove)
gems.Remove(key);
(Where KeyType is the type of key you're using. Substitute the correct type!)
Alternatively, if it is important that the gem is removed before calling OnGemCollected(), then (with key type TKey and value type TValue) do it like this:
var itemsToRemove = new List<KeyValuePair<TKey, TValue>>();
foreach (var gem in gems)
{
gem.Value.Update(gameTime);
if (gem.Value.BoundingCircle.Intersects(Player.BoundingRectangle))
itemsToRemove.Add(gem);
}
foreach (var item in itemsToRemove)
{
gems.Remove(item.Key);
OnGemCollected(item.Value, Player);
}
As the other answers say, a foreach is designed purely for iterating over a collection without modifying it as per the documenation:
The foreach statement is used to iterate through the collection to get
the desired information, but should not be used to change the contents
of the collection to avoid unpredictable side effects.
in order to do this you would need to use a for loop (storing the items of the collection you need to remove) and remove them from the collection afterwards.
However if you are using a List<T> you could do this:
lines.RemoveAll(line => line.FullfilsCertainConditions());
After going through all the answers, and being equally good. I faced a challenge where I had to modify a List and what I ended up doing worked quite well for me. So just in case anyone finds it useful. Can someone provide me feedback on how efficient it might be.
Action removeFromList;
foreach(var value in listOfValues){
if(whatever condition to remove is){
removeFromList+=()=>listOfValues.remove(value);
}
}
removeFromList?.Invoke();
removeFromList = null;
You should use the for loop instead of the foreach loop. Please refer here
Collections support foreach statement using Enumarator. Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call to MoveNext or Reset throws an InvalidOperationException.
Use for loop for collection modifying.

how to construct a list using Linq, while doing something else?

for example
foreach (var item in List<int> a)
{
b.add(item);
c+=item;
dosomething();
}
how to write this into Linq form? or is it necessary?
I guess it has the following format: var b = a.xxxx(x=>(c+=x;dosomething())).ToList()
Since LINQ is really intended to be a query language, I would say it's bad style to have queries that have secondary effects when they are evaluated. I'd personally either leave things the way they are, or change it to something like this:
var c = a.Sum();
var b = a.ToList();
foreach(var item in a)
{
DoSomething();
}
Even though you end up iterating over the list multiple times, it's much easier to glance at each line of code and know immediately what it does.
You could do this:
var b = a.Select(i => { c += i; dosomething(); return i; }).ToList();
Note that this is probably considered bad practice. The foreach loop is likely more readable and therefore more maintainable. (It will also be more performant, since there isn't a jump-to-pointer instruction being executed for each item in the list.)

Modifying list inside foreach loop

I have a construction similar to this (but a lot more complicated):
var list = new List<string>();
// .. populate list ..
foreach(var item in list)
{
DoFunction(list);
}
public void DoFunction(List<string> list)
{
if(someCondition == true)
{
// .. modify list in here ..
}
}
Now, I understand that its not possible to edit the collection you're foreaching through, but how do you jump out of the loop gracefully if you do have to edit the list (without a try catch statement)? Is there some way to tell if the list has been edited? Can you edit the list and quickly break; before it notices?
Yes, you could break, if that's what you really want. An exception won't be thrown until the for loop tries to grab the next item from the list.
But I've found it's easiest just to create and iterate across a copy of the list so you don't have to worry about it.
foreach(var item in list.ToList())
The added performance overhead of an extra, untouched list is generally negligible compared to the maintainability costs of more complex code.
Rather than use a foreach construct, a for loop would allow you to alter the list.
for (var x = 0; x < list.Count; x++) {
}
It's hard to offer useful advice without knowing what kinds of edits are being made. The pattern that I've found is has the most general-purpose value, though, to just construct a new list.
For example, if you need to look at each item and decide between removing it, leaving it as-is, or inserting items after it, you could use a pattern like this:
IEnumerable<string> butcherTheList(IEnumerable<string> input)
{
foreach (string current in input)
{
if(case1(current))
{
yield return current;
}
else if(case2(current))
{
yield return current;
yield return someFunc(current);
}
// default behavior is to yield nothing, effectively removing the item
}
}
List<string> newList = butcherTheList(input).ToList();

Categories