问题
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:
- is
true
if all the elements in the list aretrue
- is
false
if all the elements in the list arefalse
- is
null
in all other cases, thus there are bothtrue
andfalse
elements in the list or the list is empty
Until 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?
回答1:
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;
}
回答2:
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();
来源:https://stackoverflow.com/questions/57695722/linq-ternary-result-of-binary-list