I need to check if a sequence has any items satisfying some condition but at the same time NOT all items satisfying the same condition.
For example, for a sequence of 10
If you wanted to define this as a method, you could take then approach Linq takes in defining both IEnumerable
and IQueryable
extension methods. This allows for the optimal approach to be taken automatically:
public static bool SomeButNotAll(this IQueryable source, Expression> predicate)
{
if(source == null)
throw new ArgumentNullException("source");
if(predicate == null)
throw new ArgumentNullException("predicate");
return source.
Select(predicate)
.Distinct()
.Take(2)
.Count() == 2;
}
public static bool SomeButNotAll(this IEnumerable source, Func predicate)
{
if(source == null)
throw new ArgumentNullException("source");
if(predicate == null)
throw new ArgumentNullException("predicate");
using(var en = source.GetEnumerator())
if(en.MoveNext())
{
bool first = predicate(en.Current);
while(en.MoveNext())
if(predicate(en.Current) != first)
return true;
}
return false;
}
If you're using EntityFramework (or another provider that provides a CountAsync
you can also provide an asynchronous version easily:
public static async Task SomeButNotAllAsync(this IQueryable source, Expression> predicate, CancellationToken cancel)
{
if(source == null)
throw new ArgumentNullException("source");
if(predicate == null)
throw new ArgumentNullException("predicate");
cancel.ThrowIfCancellationRequested();
return await source.
Select(predicate)
.Distinct()
.Take(2)
.CountAsync(cancel)
.ConfigureAwait(false) == 2;
}
public static Task SomeButNotAllAsync(this IQueryable source, Expression> predicate)
{
return source.SomeButNotAllAsync(predicate, CancellationToken.None);
}