C# 检查IEnumerable的所有项目<;T?>;使用LINQ具有相同的值
我有一个可空类型,例如C# 检查IEnumerable的所有项目<;T?>;使用LINQ具有相同的值,c#,linq,.net-3.5,ienumerable,C#,Linq,.net 3.5,Ienumerable,我有一个可空类型,例如SomeEnum?和一组值,例如IEnumerable 如何使用LINQ检查所有项目是否具有相同的值(并获取该值) (如果不存在唯一值,则将引发异常,否则将返回该值) 如果不希望出现异常: var few=data.Distinct().Take(2).ToList(); if(few.Count==1) { var value = few[0]; ... } 公共静态bool AllEqual(此IEnumerable值),其中T:struct { 如果
SomeEnum?
和一组值,例如IEnumerable
如何使用LINQ检查所有项目是否具有相同的值(并获取该值)
(如果不存在唯一值,则将引发异常,否则将返回该值)
如果不希望出现异常:
var few=data.Distinct().Take(2).ToList();
if(few.Count==1) {
var value = few[0];
...
}
公共静态bool AllEqual(此IEnumerable值),其中T:struct
{
如果(!values.Any())返回true;
T?first=值。first();
返回值.Skip(1).All(v=>first.Equals(v));
}
编辑:要获取值,可以返回如下元组(success,value):
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);
}
公共元组AllEqual(IEnumerable值),其中T:struct
{
if(!values.Any())返回Tuple.Create(true,(T?)null);
T?first=值。first();
bool equal=values.Skip(1).All(v=>v.Equals(first));
返回Tuple.Create(equal,equal?first:(T?)null);
}
或者您可以使用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));
}
public static bool AllEqual(这是IEnumerable value,out T?value),其中T:struct
{
值=空;
如果(!values.Any())返回true;
T?first=值。first();
值=第一;
返回值.Skip(1).All(v=>first.Equals(v));
}
也可以很好地工作。懒惰,对于空序列返回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;
}
}
public static bool AllEqual(此IEnumerable源,out T值)
{
使用(var enumerator=source.GetEnumerator())
{
如果(!enumerator.MoveNext())
{
值=默认值(T);
返回true;
}
值=枚举数。当前值;
var comparer=EqualityComparer.Default;
while(枚举数.MoveNext())
{
如果(!comparer.Equals(value,enumerator.Current))
{
返回false;
}
}
返回true;
}
}
Take(2)
如果Distinct()
返回长度为1的集合,将引发异常,不是吗?@abatishchev:不,不会。它是在“尽力而为”的基础上工作的。@abatishchev Take(n)是Take最多,而不是Takeexactly@abatishchev-还要注意,这些是序列,而不是集合(直到ToList)。一个微妙的区别,也许-直到您获得高容量…这对于LINQ to对象更可取,因为它会在发现一个不相等的值时立即退出。在LINQ中,它会导致3次往返。@stripling-这个问题的所有答案都会短路。EF无论如何都会将其视为L2O,因为它不使用Queryable,除非接口是IQueryable@Marc格雷威尔:说得好。我不知道Distinct是否是可靠的。应该假设它是。@stripling-值得注意的是,因为并非所有序列都是可重复的,即使在L2O中,也应该避免多次重复reads@abatishchev-假设你的意思是!values.Any()
检查空序列-此实现假定空序列中的所有项都为空,并且“value”为null。您可能希望抛出一个异常values.All(…)
返回序列中的每个项是否满足某些条件-在本例中,每个其他项是否等于第一项(因此都相等)。好主意。并且可以使用与Lee's way+1相同的扩展方法进行包装,以避免像Distinct这样的中间列表和像first answer这样的多次迭代,这是一些序列不支持的。绝对是这个列表中最好的实现。我同意Mike的观点-非常好的解决方案。但并没有像问题的作者所问的那个样使用LINQ。
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));
}
data.Distinct().Count() == 1;
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;
}
}