Flipping a Boolean When All Values Meet a Condition with LINQ

Every once in a while, a seemingly simple coding problem can throw a chicken-or-egg situation at you. You’ve built complex software in mere hours, how can a `for` loop throw you off like this…!?!?

Don’t worry, it happens…

Here’s a quick example: you want to loop through a collection and flip a `boolean` if a condition is met by all of the elements in the collection.

So you try something like this:

``````public class Vector {
public float DX { get; set; }
public float DY { get; set; }
}
...
[Fact]
public void Flip_bool_on_collection_condition() {

var vectors = new List<Vector>() {
new Vector() {DX = 0.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 0.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f}
};

bool myBool = false;
for (int i = 0; i < vectors.Count; i++) {
if (vectors[i].DX > 0) {
myBool = true;
}
else {
myBool = false;
}
}
_output.WriteLine("All vectors.DX > 0? " + myBool);
}
``````
``````All vectors.DX > 0? True
``````

`myBool` is going to flick off and on until it reaches the last element. `All vectors.DX > 0` is not `True` it’s a lie!

It was probably obvious to you while you read the code, but what if you’ve been in a state of flow for 2 hours?… Goodbye flow…

There are a few ways to make the code work the way you want it to, but there’s one that will help you stay in your flow because of its readability and brevity:

``````[Fact]
public void Flip_bool_on_collection_condition_1() {

var vectors = new List<Vector>() {
new Vector() {DX = 0.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 0.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f}
};

bool myBool = vectors.All(vector => vector.DX > 0);

_output.WriteLine("All vectors.DX > 0? " + myBool);
}``````
``````All vectors.DX > 0? False
``````

So:

``````[Fact]
public void Flip_bool_on_collection_condition() {

var vectors = new List<Vector>() {
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f},
new Vector() {DX = 1.0f, DY = 0.0f}
};

bool myBool = vectors.All(vector => vector.DX > 0);

_output.WriteLine("All vectors.DX > 0? " + myBool);
}
``````
``````All vectors.DX > 0? True
``````

We aren’t being lied to anymore. Enumerable.All is used to determine “whether all elements in a sequence satisfy a condition.”

Sure, we could have set `myBool` to `true` and flipped it to `false` when we found an element that didn’t satisfy the condition. We could have also used `break` to break out of the loop when we found the element.

I think the LINQ way is fine for our purpose here. It’s simple and clear what our intention is. It’s important to keep in mind that there are performance implications with LINQ. In a tight-loop situation, we want to avoid instantiating objects and excessive string manipulation inside the loop.

We also want to be aware that `.All()` evaluates to `true` for empty lists:

``````[Fact]
public void Flip_bool_on_collection_condition() {

var vectors = new List<Vector>() {
};

bool myBool = vectors.All(vector => vector.DX > 0);

_output.WriteLine("All vectors.DX > 0? " + myBool);
}
``````
``````All vectors.DX > 0? True
``````

So we can add a `.Any()` to make sure there are elements in the list before we evaluate the condition:

``````[Fact]
public void Flip_bool_on_collection_condition() {

var vectors = new List() {
};

bool myBool = vectors.Any() && vectors.All(vector => vector.DX > 0);

_output.WriteLine("All vectors.DX > 0? " + myBool);
}``````
``````All vectors.DX > 0? False
``````

Summary

We were perfectly fine in our flow when suddenly a little problem/solution tripped us up when we wrote our first pass on it. All we wanted to do was flip a bool if all the elements in a collection met a condition.

Luckily, LINQ `.All()` rescued us with a simple and clear solution to meet the requirement. We have to be aware of the performance implications if we are doing something more complex inside the LINQ statement so that memory doesn’t get away from us. We also need to be aware that `.All()` evaluates to `true` for empty lists. Adding `.Any()` to make sure there are elements in the list covers that case.