Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a better way of calling LINQ Any + NOT All?

Tags:

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 items I want to have TRUE if the sequence has at least one that satisfy the condition but not all:

  • 10 items satisfying, 0 items not, result is FALSE
  • 0 items satisfying, 10 items not, result is FALSE
  • 1 item satisfying, 9 items not, result is TRUE
  • 9 items satisfying, 1 item not, result is TRUE

I know I could to this:

mySequence.Any (item => item.SomeStatus == SomeConst) && !mySequence.All (item => item.SomeStatus == SomeConst) 

But this is not optimal.

Is there a better way?

like image 509
Stécy Avatar asked May 01 '15 19:05

Stécy


People also ask

What is the difference between any and all in LINQ?

All() determines whether all elements of a sequence satisfy a condition. Any() determines whether any element of a sequence satisfies the condition.

Which is faster count or any?

First, Any() without parameters is quicker than Count() as it does not iterate through the whole collection. Second, Any() improves the readability of your code, indicating that the developer just wants to check if there are any items in the collection and isn't concerned with the exact number of items.

Why is LINQ lazy?

Yes, LINQ uses lazy evaluation. The database would be queried when the foreach starts to execute, but it would fetch all the data in one go (it would be much less efficient to do millions of queries for just one result at a time).

What are the different LINQ query methods?

There are the following two ways to write LINQ queries using the Standard Query operators, in other words Select, From, Where, Orderby, Join, Groupby and many more. Using lambda expressions. Using SQL like query expressions.


Video Answer


2 Answers

You'll like this.

var anyButNotAll = mySequence     .Select(item => item.SomeStatus == SomeConst)     .Distinct()     .Take(2)     .Count() == 2; 

The Take(2) stops it iterating over any more elements than it has to.

like image 172
Rawling Avatar answered Oct 07 '22 13:10

Rawling


If your concern is iterating through all of the elements in a large collection, you're okay - Any and All will short-circuit as soon as possible.

The statement

mySequence.Any (item => item.SomeStatus == SomeConst) 

will return true as soon as one element that meets the condition is found, and

!mySequence.All (item => item.SomeStatus == SomeConst) 

will return true as soon as one element does not.

Since both conditions are mutually exclusive, one of the statements is guaranteed to return after the first element, and the other is guaranteed to return as soon as the first element is found.


As pointed out by others, this solution requires starting to iterate through the collection twice. If obtaining the collection is expensive (such as in database access) or iterating over the collection does not produce the same result every time, this is not a suitable solution.

like image 23
BJ Myers Avatar answered Oct 07 '22 13:10

BJ Myers