如何检查所有列表项是否具有相同的值并将其返回,如果不是,则返回"otherValue"?

Ian*_*ose 111 c# linq

如果列表中的所有项都具有相同的值,那么我需要使用该值,否则我需要使用"otherValue".我想不出一个简单明了的做法.

另请参阅编写循环的简洁方法,该循环具有集合中第一个项目的特殊逻辑.

Kei*_*thS 144

var val = yyy.First().Value;
return yyy.All(x=>x.Value == val) ? val : otherValue; 
Run Code Online (Sandbox Code Playgroud)

我能想到的最干净的方式.您可以通过内联val使其成为单行,但First()将被评估n次,执行时间加倍.

要合并评论中指定的"空集"行为,您只需在上述两个行之前再添加一行:

if(yyy == null || !yyy.Any()) return otherValue;
Run Code Online (Sandbox Code Playgroud)

  • @adrift:`All`会在遇到`x.Value!= val`序列的元素`x`时终止.类似地,`Any(x => x.Value!= val)`一旦遇到`x.Value!= val`序列的元素`x`就会终止.也就是说,"All"和"Any"都表现出"短路",类似于"&&"和"||"(实际上是"All"和"Any"). (12认同)
  • 微优化:`返回yyy.Skip(1).All(x => x.Value == val)吗?val:otherValue;` (3认同)

Jer*_*ell 91

所有平等的快速测试:

collection.Distinct().Count() == 1
Run Code Online (Sandbox Code Playgroud)

  • 更清洁,是的,但在一般情况下性能较差; Distinct()保证遍历集合中的每个元素一次,并且在每个元素不同的最坏情况下,Count()将遍历整个列表两次.Distinct()还会创建一个HashSet,因此它的行为可以是线性的,而不是NlogN或更糟,这会增加内存使用量.All()在所有元素相同的最坏情况下进行一次完整传递,并且不创建任何新集合. (15认同)
  • 小心,`.Distinct()`并不总是按预期工作 - 特别是当您使用对象时,请参阅[this](http://stackoverflow.com/q/1365748/1016343)问题.在这种情况下,您需要实现IEquatable接口. (4认同)
  • 人们可以在“Distinct”中使用相等比较器来与特定类一起使用。或者,按照我选择使用此答案的方式,使用“Select”首先映射目标属性,例如:“collection.Select(x => x.Property).Distinct().Count() == 1” (3认同)
  • +1比KeithS的解决方案IMO更清洁.如果要允许空集合,可能需要使用`collection.Distinct().Count()<= 1`. (2认同)
  • @KeithS,我希望您现在意识到,“Distinct”根本不会遍历集合,而“Count”将通过“Distinct”的迭代器进行一次遍历。 (2认同)

Eri*_*ert 20

虽然您当然可以使用现有的序列运算符构建这样的设备,但在这种情况下,我倾向于将此编写为自定义序列运算符.就像是:

// Returns "other" if the list is empty.
// Returns "other" if the list is non-empty and there are two different elements.
// Returns the element of the list if it is non-empty and all elements are the same.
public static int Unanimous(this IEnumerable<int> sequence, int other)
{
    int? first = null;
    foreach(var item in sequence)
    {
        if (first == null)
            first = item;
        else if (first.Value != item)
            return other;
    }
    return first ?? other;
}
Run Code Online (Sandbox Code Playgroud)

这非常清楚,简短,涵盖所有情况,并且不会不必要地创建序列的额外迭代.

将其作为一种可用的通用方法留作IEnumerable<T>练习.:-)


Jus*_*ner 13

return collection.All(i => i == collection.First())) 
    ? collection.First() : otherValue;.
Run Code Online (Sandbox Code Playgroud)

或者,如果您担心为每个元素执行First()(这可能是一个有效的性能问题):

var first = collection.First();
return collection.All(i => i == first) ? first : otherValue;
Run Code Online (Sandbox Code Playgroud)

  • 或者更糟糕的是,如果查询是数据库查询并且调用"First",则每次都会再次访问数据库. (4认同)