Is there an opposite of LINQ's All method? - c#

I'm currently using
a_list.All(item => !(item.field_is_true == true))
which works well, but I'd like to know if there was a proper LINQ method to do the opposite of all.

All() checks that a given Predicate returns true for all items. In terms of framework development, it wouldn't make any sense to write a seperate method that checks that a given Predicate returns false for all items, as it is so easy to "not" a predicate.
However, you can write your own extension method:
public static bool None<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
return !source.Any(predicate);
}

The exact opposite of All() is essentially None, but since LINQ has no None() method, you can accomplish the same result through !set.Any().
!a_list.Any(item => item.matches == true)
This will produce true if none of the items in a_list have a matches value that is true.
Another example:
names.All(item => item.StartsWith("R"))
is true if all of the items in names start with R (as you know already).
!names.Any(item => item.StartsWith("R"))
is true if none of the items in names start with R.
Based on your comment below, it sounds like you might just be looking for a way to accomplish the same result as your current code snippet, but in a different way. This should provide the same result as your current code, but without the ! in the predicate:
!a_list.Any(item => item.matches == true)
This can be further simplified to:
!a_list.Any(item => item.matches)
I'd imagine yours could be simplified as well, to this:
a_list.All(item => !item.matches)
There's rarely a good reason to explicitly compare a boolean value with true or false.

you wrote:
a_list.All(item => !(item.field_is_true == true))
that is like doing:
a_list.All(item => item.flag== false) // more readable to me...
//return true if all of the items have a **flase** value on their flag
you can also use .any() to achieves the same result:
!a_list.Any(item => item.flag==true)
as for performence issues: .any() vs .all() - both would have identical performance
(when linq to object is used) , find more here : LINQ: Not Any vs All Don't

Rather than negate the All() condition, simply use the Any() with the same predicate and treat the returned boolean appropriately.
So, rather than:
bool conditionDoesntExist = a_list.All(item => !(item.field_is_true == true));
you can have
bool conditionDoesExist = a_list.Any(item => item.field_is_true == true)
Note the change in name of the flag. (Of course I'm overlooking semantic stuff like the original predicate could have been written as item => item.field_is_true == false or simply item => !item.field_is_true ).
If you want to keep the flag name the same then still use the Any() but negate it:
bool conditionDoesntExist = !a_list.Any(item => item.field_is_true == true);

All
a_list.All(item => item.condition)
Some
a_list.Any(item => item.condition)
Not all
!a_list.All(item => item.condition)
or:
a_list.Any(item => !(item.condition))
None
!a_list.Any(item => item.condition)
or
a_list.All(item => !(item.condition))

Related

Can this expression be simplified?

I am running code from a Room object to get all the IRoomDwellers of a specific type into a list. All IRoomDwellers are stored in a static Dictionary<IRoomDweller,Room>.
However, this is basically my first time using Linq, and I feel (though the code appears to work) that the expression is rather unwieldy. For one, I don't really get what value the GroupBy is adding, but it does not appear to work without it.
The method is as follows:
private List<T> GetDwellers<T>() where T : IRoomDweller {
return RoomDwellers
.GroupBy(z => z.Value)
.SelectMany(z => z)
.Where(z => z.Value == this && z.Key is T)
.Select(z => (T) z.Key)
.ToList();
}
What function does the GroupBy actually serve (I cribbed that from an example when my initial attempt didn't work)? And can this expression otherwise be simplified/made to be more performant?
It's not ideal to have a dictionary (which is intended to be used to get a Room, if you have a RoomDweller) and use it the wrong way round (you have a Room and want to get a RoomDweller) but:
return RoomDwellers.Where(rdkvp => rdkvp.Value == this && rdkvp.Key is T)
.Select(rdkvp => rdkvp.Key)
.ToList();
RoomDwellers is a list of KeyValuePair, Key is a RoomDweller, Value is a Room.. So you can enumerate the list of KVPs, choosing those where the Value is this room, and then return the associated Key (the RoomDweller)

Is there default value for expression, which doesn't influence on it?

I have a filter by some projects in my app. It works using Expression query, which is NULL at the start.
During filtering there are a lot of IF statements, which bodies has check if query is NULL. I need to avoid repeats, but the problem is that I can't add condition like query.And(exp) if query is NULL.
So before adding condition - the query variable must have value. My first idea is to add condition and remove it before applying filter, but I couldn't remove that from the body, because it's not a string and I haven't found such methods for it. Then I've tried to add condition, which tells filter to take projects with ID equal to MAXINT, but that doesn't work, because query body looks like { p => p.ID == 2147483647 And also }. Not OR, but AND ALSO. So there are 0 projects as result.
Expression<Func<Project, bool>> query = null, exp = null;
This is, how it works now in each IF statement:
if (filter.ViewSomeProjects)
{
exp = p => (some conditions);
query = query != null ? query.And(exp) : exp;
}
This is, how I want it to work:
if (filter.ViewSomeProjects)
{
query.And(some conditions);
}
So I can't do it like I want, while query is NULL at the beginning.
My questions are: Is there any way to delete part of expression body?
Is it possible to add useless condition to the expression, which won't influence on result?
Predicate Builder by Joe Albahari has a True and False that you can use as the starting point.
public static Expression<Func<T, bool>> True<T> () { return f => true; }
public static Expression<Func<T, bool>> False<T> () { return f => false; }
If you start from one of these, you can then build up your query depending on what the default behaviour is (generally True works fine when adding restrictions to a default of "all results".)

Weird Lambda behavior in string equality

I have an array of strings obj[] values, but trying to use equality seems to be different than what I might expect, can someone clarify this?
content of values is ["train","train"];
var first = values.First();
values.Skip(1).All(v => Equals(v, first))
false
values.Skip(1).All(v => v.Equals(first))
true
Equals(values[0], values[1])
true
Equals(values[1], values[0])
true
values.Skip(1).All(v => Equals(v, first) == true)
false
values.Skip(1).Any(v => Equals(v, first) == false)
true
Any clue why it returns false?
Edit1: I have wrote a unit test and it passes, I'm checking if the strings have different cultures as #Michael Randall suggested
Equals implementation on MSDN
Your problem must be your input
Note : You should consider doing proper string comparison. Best Practices for Using Strings in .NET
However as you can see with the appropriate input, your code actually works
var first = "train";
var values = new object[]{"train", "train"};
Console.WriteLine(values.Skip(1).All(v => Equals(v, first)));
Console.WriteLine(values.Skip(1).All(v => v.Equals(first)));
Console.WriteLine(Equals(values[0], values[1]));
Console.WriteLine(Equals(values[1], values[0]));
Console.WriteLine(values.Skip(1).All(v => Equals(v, first) == true));
Console.WriteLine(values.Skip(1).Any(v => Equals(v, first) == false));
Output
True
True
True
True
True
False
You can test it here
#TheGeneral answer is usually the correct one, but in my case restarting the machine removed this issue. my guess it was the debugger have a bug.

Can I use the .Min() Linq extension method on a bool type?

I want to find if I have any bools that are false in a collection. Can I use the following code to find it?
this.MyList.Min(e => e.MyBool)
I'm hoping this will return false if there is a false in the collection.
You can use (renamed the collection for reasons of readability):
bool anyFalse = myBools.Any(b => !b);
or
bool anyFalse = !myBools.All(b => b);
both are efficient since they break on the first false.
If there are complex objects in the collection(as it seerms to be) use:
bool anyFalse = MyList.Any(x => !x.MyBool);
or
bool anyFalse = !MyList.All(x => x.MyBool);
Yes, it will work because Boolean is IComparable<Boolean> but it's awkward and thus it's harder to understand the intent of your code.
Additionally, your code will have to go through the whole sequence just to find out if there's a false, and it will throw if the sequence is empty.
Use All instead:
MyList.All(item => item.MyBool)
This will return false if there's any false value in the sequence. If the sequence is empty, All will return true.

Why does IEnumerable.Any return True for a collection of False-booleans?

I recently needed to check two lists to see if the type of data matched the expected type, at the expected index. So I did a check on each element x at each index i and stored this comparison as a boolean, I then called Any to see if any of the booleans where true. However, the following statement always throws the exception.
var values = new object[] {(UInt64) 40, (Boolean) true, (Double) 45.3};
var types = new[] {typeof (UInt64), typeof (Boolean), typeof (Double)};
if (types.Select((x, i) => values[i].GetType() != x).Any())
throw new Exception();
(I know why, but after spending a few minutes debugging I thought it would make a good question).
Enumerable.Any without argument just checks if the sequence contains elements. If you want to know if there are any trues you have to use the overload:
bool anyTrue = bools.Any(b => b);
Any doesn't check what's in your sequence. It looks for if there is Any element in the sequence.So whether you have a sequence of true values of false doesn't matter.
Any() doesn't do what you think it does. Without a lambda expression in Any(), it will just check if there is any element in the enumerable it is called on.
You either want:
types.Select((x, i) => values[i].GetType() != x).Any(x => x)
or maybe
types.Where((x, i) => values[i].GetType() != x).Any()
You need to use this overload of the Any() method. The overload you are using just returns true if the sequence contains stuff, it doesn't care what the values are. To check the booleans and only return if one them is true, your code would need to be
if (types.Select((x, i) => values[i].GetType() != x).Any(x => x))
throw new Exception();

Categories