Reputation: 1312
Assume I have a list of binary parameters (in reality it is a list of checkboxes' IsChecked.Value
property). I'm trying to get the bool?
(ternary) result that:
true
if all the elements in the list are true
false
if all the elements in the list are false
null
in all other cases, thus there are both true
and false
elements in the list or the list is emptyUntil now I came up with the solution that requires iterating over the list twice (checking whether all elements are either true
or false
) and then comparing the results to deciding whether to return true
, false
or null
.
This is my code:
bool checkTrue = myListOfBooleans.All(l => l);
bool checkFalse = myListOfBooleans.All(l => !l);
bool? result = (!checkTrue && !checkFalse) ? null : (bool?)checkTrue;
How can I achieve it in only one iteration over the list?
Upvotes: 1
Views: 87
Reputation: 32296
You could do that by using Aggegrate
public bool? AllSameValue(List<bool> myListOfBooleans)
{
if(myListOfBooleans.Count == 0) return null; // or whatever value makes sense
return myListOfBooleans.Cast<bool?>().Aggregate((c, a) => c == a ? a : null);
}
That casts your values to bool?
so that you can then compare them and return the value if that they all match or null if there is a difference.
Of course you could exit early by taking the first one and using All
to see if the rest match or not.
public bool? AllSameValue(List<bool> myListOfBooleans)
{
if(myListOfBooleans.Count == 0) return null; // or whatever value makes sense
bool first = myListOfBooleans[0];
return myListOfBooleans.All(x => x == first ) ? first : null;
}
Upvotes: 2
Reputation: 43906
You can simply count the true
values:
int c = myListOfBooleans.Count(l => l);
bool? result = c == myListOfBooleans.Count
? (bool?)true
: (c == 0 ? (bool?)false : null);
Note that this is true
for an empty list, you may want to tweak that according to your required logic.
For a better performance (though I don't think it matters in a UI context) you could write an extension that could even return early if the result is clear (instead of iterating through the whole list):
public static bool? AllOrNothing(this IEnumerable<bool> list)
{
if (list == null) throw new ArgumentNullException(nameof(list));
using(var enumerator = list.GetEnumerator())
{
if (!enumerator.MoveNext())
return null; // or true or false, what you need for an empty list
bool? current = enumerator.Current;
while(enumerator.MoveNext())
if (current != enumerator.Current) return null;
return current;
}
}
And use it:
bool? result = myListOfBooleans.AllOrNothing();
Upvotes: 2