二进制列表的 LINQ 三元结果
LINQ ternary result of binary list
假设我有一个二进制参数列表(实际上它是一个复选框列表'IsChecked.Value
属性)。我正在尝试获得 bool?
(三元)结果:
- is
true
if all 列表中的元素是true
- is
false
if all 列表中的元素是false
在所有其他情况下 - 是
null
,因此列表中同时存在 true
和 false
元素,或者列表为空
直到现在,我提出的解决方案需要遍历列表两次(检查所有元素是 true
还是 false
),然后比较结果以决定是否 return true
, false
或 null
.
这是我的代码:
bool checkTrue = myListOfBooleans.All(l => l);
bool checkFalse = myListOfBooleans.All(l => !l);
bool? result = (!checkTrue && !checkFalse) ? null : (bool?)checkTrue;
我怎样才能在列表的一次迭代中实现它?
您可以简单地计算 true
个值:
int c = myListOfBooleans.Count(l => l);
bool? result = c == myListOfBooleans.Count
? (bool?)true
: (c == 0 ? (bool?)false : null);
请注意,这是一个空列表 true
,您可能需要根据您所需的逻辑进行调整。
为了获得更好的性能(尽管我认为这在 UI 上下文中并不重要)您可以编写一个扩展,如果结果明确(而不是迭代),甚至可以 return 提早通过整个列表):
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;
}
}
并使用它:
bool? result = myListOfBooleans.AllOrNothing();
您可以使用 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);
}
这会将您的值转换为 bool?
,这样您就可以将它们与 return 比较,如果它们都匹配则为值,如果有差异则为 null。
当然,您可以提前退出,方法是选择第一个并使用 All
查看其余是否匹配。
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;
}
假设我有一个二进制参数列表(实际上它是一个复选框列表'IsChecked.Value
属性)。我正在尝试获得 bool?
(三元)结果:
- is
true
if all 列表中的元素是true
- is
false
if all 列表中的元素是false
在所有其他情况下 - 是
null
,因此列表中同时存在true
和false
元素,或者列表为空
直到现在,我提出的解决方案需要遍历列表两次(检查所有元素是 true
还是 false
),然后比较结果以决定是否 return true
, false
或 null
.
这是我的代码:
bool checkTrue = myListOfBooleans.All(l => l);
bool checkFalse = myListOfBooleans.All(l => !l);
bool? result = (!checkTrue && !checkFalse) ? null : (bool?)checkTrue;
我怎样才能在列表的一次迭代中实现它?
您可以简单地计算 true
个值:
int c = myListOfBooleans.Count(l => l);
bool? result = c == myListOfBooleans.Count
? (bool?)true
: (c == 0 ? (bool?)false : null);
请注意,这是一个空列表 true
,您可能需要根据您所需的逻辑进行调整。
为了获得更好的性能(尽管我认为这在 UI 上下文中并不重要)您可以编写一个扩展,如果结果明确(而不是迭代),甚至可以 return 提早通过整个列表):
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;
}
}
并使用它:
bool? result = myListOfBooleans.AllOrNothing();
您可以使用 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);
}
这会将您的值转换为 bool?
,这样您就可以将它们与 return 比较,如果它们都匹配则为值,如果有差异则为 null。
当然,您可以提前退出,方法是选择第一个并使用 All
查看其余是否匹配。
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;
}