使用LINQ检查IEnumerable <T?>的所有项是否具有相同的值

aba*_*hev 11 c# linq ienumerable .net-3.5

我有一个可以为空的类型,例如SomeEnum?一组值,例如IEnumerable<SomeEnum?>.

如何使用LINQ检查所有项目是否具有相同的值(并获取此值)?

Cle*_*ent 19

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

效果也不错.


Lee*_*Lee 11

public static bool AllEqual<T>(this IEnumerable<T?> values) where T : struct
{
        if (!values.Any()) return true;
        T? first = values.First();
        return values.Skip(1).All(v => first.Equals(v));
}
Run Code Online (Sandbox Code Playgroud)

编辑:要获得该值,您可以返回一个元组(成功,值),如下所示:

public Tuple<bool, T?> AllEqual<T>(IEnumerable<T?> values) where T : struct
{
    if(! values.Any()) return Tuple.Create(true, (T?)null);
    T? first = values.First();
    bool equal = values.Skip(1).All(v => v.Equals(first));
    return Tuple.Create(equal, equal ? first : (T?)null);
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用out参数:

public static bool AllEqual<T>(this IEnumerable<T?> values, out T? value) where T : struct
{
    value = null;
    if (!values.Any()) return true;

    T? first = values.First();
    value = first;

    return values.Skip(1).All(v => first.Equals(v));
}
Run Code Online (Sandbox Code Playgroud)

  • 这对于LINQ to Objects来说是首选,因为它会在找到一个不相等的值时立即保释.在LINQ to Entities等中,它将导致3次往返. (2认同)
  • @stripling - 并且作为一个注意事项,因为并非所有序列都是可重复的,即使在L2O中也应该避免多次读取 (2认同)

Mar*_*ell 5

var value = data.Distinct().Single();
Run Code Online (Sandbox Code Playgroud)

(如果没有一个唯一值,则抛出异常,否则返回该值)

如果您不想要例外:

var few=data.Distinct().Take(2).ToList();
if(few.Count==1) {
    var value = few[0];
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • @abatishchev:不,它不会.它以"尽力而为"为基础. (2认同)
  • @abatishchev Take(n)取*最多*,不取*正好* (2认同)

小智 5

延迟并为空序列返回true:

public static bool AllEqual<T>(this IEnumerable<T> source, out T value)
{
    using (var enumerator = source.GetEnumerator())
    {
        if (!enumerator.MoveNext())
        {
            value = default(T);
            return true;
        }

        value = enumerator.Current;
        var comparer = EqualityComparer<T>.Default;

        while (enumerator.MoveNext())
        {
            if (!comparer.Equals(value, enumerator.Current))
            {
                return false;
            }
        }

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)