二进制列表的 LINQ 三元结果

LINQ ternary result of binary list

假设我有一个二进制参数列表(实际上它是一个复选框列表'IsChecked.Value 属性)。我正在尝试获得 bool?(三元)结果:

直到现在,我提出的解决方案需要遍历列表两次(检查所有元素是 true 还是 false),然后比较结果以决定是否 return true, falsenull.

这是我的代码:

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;
}