Avoid to display NAN in datagrid? - c#

I can use a converter for this task, but my situation is this:
I've an object with several properties, I evaluate the double of each property and return the result of a function, the code explain better:
var partialFinalForecast = poisson.GetPartialFinalForecast();
partialFinalForecast.GetType().GetProperties()
.Where(x => x.PropertyType == typeof(double)).ToList()
.ForEach(x => x.SetValue(partialFinalForecast, Math.Round((double)x.GetValue(partialFinalForecast), 2)));
sometimes happen that this return NAN, how can I avoid this result directly on this query?

You could replace (double)x.GetValue(partialFinalForecast) with Double.IsNaN((double)x.GetValue(partialFinalForecast)) ? 0 : (double)x.GetValue(partialFinalForecast), but this is hardly a good approach (as mentioned by oerkelens)...

Related

Linq sorting with nullable object

could you please help me!
I have object list like:
item[0].title = apple
item[0].data.weight = 1
item[1].title = lemon
item[1].data = null
item[2].title = melon
item[2].data.weight = 3
I would like to sort it (ASC and DESC) by weight with null data.
I tried like this:
item.OrderBy(x => x.data == null).ThenBy(x => x.data.weight); // failed
item.Where(x => x.data != null).OrderBy(x => x.data.weight); // ok, but as result only two records
So how i can sort items and receive all results.
ASC at first should be data with null.
DESC at first data with max weight and null at the end of the list.
item.OrderBy(x => x.data == null).ThenByDescending(x => x.data == null ? 0 : x.data.weight);
I am assuming weight is an int, otherwise provide the default value based on type.
Given you're only shipping fruit, and not, say, light, you can treat items having null data as having weight 0. Alternatively, just pick any value that's lower than the possible, valid values in order to put the null items at the top when sorting ascendingly.
You can express that like this:
var ordered = item.OrderBy(x => x.data == null ? 0 : x.data.weight);
You could use something like this: (assuming C# 6 or above)
item.OrderBy(x => x.data?.weight ?? int.MinValue);
This makes use of the new C#6 null-conditional and null-coalescing operators - if you need something applicable in lower versions of C#, you can use a ternary operator, like this:
item.OrderBy(x => x.data != null ? x.data.weight : int.MinValue);
If it's possible that you could have x.data.weight being int.MinValue, then you would need to do something like what you were doing before, but the second linq method should make use of the above lambda/s.
You can do this a few ways, one way would be to have a value replacing the null values using ternary conditional operator on the order by or filtering out the items without a value and concatenating them to the enumerable after you've sorted the objects with values.
By conditionally providing a value for items with null
This is, in my opinion, the best way, and it performs better. You only enumerate over the collection once, versus the other method where you enumerate to determine if each element has a value then order, and then check for the items without a value
item.OrderBy(x => x.data != null ? x.data.weight : int.MinValue)
Filtering and then concatenating the items without a value
There are times where this could possibly be the better solution. One example would be if you want to use a different method for ordering the values when they are missing the property you are looking for.
item.Where(x => x.data != null)
.OrderBy(x => x.data.weight)
.Concat(item.Where(a=>a.data == null))

Handling null field in aggregate using linq

I have come across a scenario where i am summing in my LINQ query.
The property could have actually NULL in database.
However, when we apply aggregate i.e. SUM on same field in collection using LINQ it calculates/returns 0 for null
I am avoiding sum for null field as following.
TotalDays = x.Select(y => y.day.HasValue ? x.Sum(z => z.day) : null).FirstOrDefault(),
Is it nice way or could have even better?
Null values sum to zero because naturally they can neither add nor subtract to the tally so generally one wants zero in such cases.
Consider:
(new int?[]{0, null, 3, 2}).Sum() // result is 5. Other linq providers do similar.
Where this can sometimes cause a problem is if you want to note all-null result-sets separately:
(new int?[]{null, null}).Sum() // result is 0, but maybe we want to note that there was indeed no values.
We could do this with:
source.Any(x => x.HasValue) ? source.Sum() : default(int?);
Which to bring back to your example would be:
int? totalDays = x.Any(y => y.day.HasValue) ? x.Sum(y => y.day) : default(int?);
However you might prefer to do:
int? totalDays = x.Sum(y => y.day);
if (totalDays == 0 && y.All(y => !y.day.HasValue))
totalDays = null;
Then you only examine the set to see if all values are null in the case of receiving the 0 result (any other result is not possible in this case).
Checking Any() first is more efficient when all-null results are more common, and doing Sum() first is more efficient when all-null results less common, because in each case you are only doing two operations in the less common case.

Optimize Linq in C#

I have columns list in which I need to assign Isselected as true for all except for two columns. (Bug and feature). I have used this following code to achieve it and working fine, but is there any quick or easy way to achieve the same?
DisplayColumns.ToList().ForEach(a => a.IsSelected = true);
DisplayColumns.ToList().Where(a => a.ColumnName == "Bug" || a.ColumnName == "Feature").ToList().ForEach(a => a.IsSelected = false);
Thanks in advance
I have used this following code to achieve it and working fine, but is there any quick or easy way to achieve the same?
Well there's a cleaner way to achieve it in my view - just don't use lambdas etc at all:
foreach (var item in DisplayColumns)
{
item.IsSelected = item.ColumnName != "Bug" && item.ColumnName != "Feature";
}
You can make the decision in one go - it's false if the column name is either "bug" or "feature"; it's true otherwise. And you don't need to call ToList and use ForEach when the C# language has a perfectly good foreach loop construct for when you want to execute some code using each item in a collection.
I love LINQ - it's fantastic - but its sweet spot is querying (hence the Q) rather than manipulation. In this case only the ToList part is even part of LINQ - List<T>.ForEach was introduced in .NET 2.0, before LINQ.
Sure, you can assign the IsSelected at once.
DisplayColumns.ToList().ForEach(a => a.IsSelected = !(a.ColumnName == "Bug" || a.ColumnName == "Feature"));
Provided that DisplayColumns isn't a projection of an anonymous type (in which case the properties are not re-assignable), you'll be able to change the flag in a single pass iteration through the collection.
You can also use Contains to ease the comparison. At class scope:
private static readonly string[] _searches = new [] {"Bug", "Feature"}
In your method:
DisplayColumns
.ToList() // For List.ForEach, although not #JonSkeet's caveat re mutating in Linq
.ForEach(a => a.IsSelected = !_searches.Contains(a.ColumnName));
Edit
As others have mentioned, creation of a new list simply to gain access to .ForEach to change objects in the (original) collection is wasteful and changes will be lost on a collection of value types. Rather, iterate over the original collection with foreach (or even for).
Firstly you only need to call ToList() once when creating a collection from your IEnumerable.
doing this after each operator is costly and redundant.
Secondly just change your condition . all true except for the tow.
DisplayColumns.Where(a => a.ColumnName != "Bug" && a.ColumnName != "Feature").ForEach(a => a.IsSelected = true).ToList();
Edit :
I'm sorry i like a part john's answer since this can be a re occurring thing , or IsSelected could be a Nullable , any ways lets keep it as general as possible .
I also like Stuart's approach , with the collection ( i also thought of it but didn't want to confuse . so let's give the best of all worlds.
when using linq we are actually building an expression tree at the end of which we can choose to materialize into a collection.
there for _searchs can change and each time we materialize that expression we do it with the values currently in that collection , thous making our code much more general .
private static readonly string[] _searches = new [] {"Bug", "Feature"}
DisplayColumns.ForEach(a => a.IsSelected = !_searchs.Contains(a.ColumnName)).ToList();
I'm assuming ForEach is an Extension method for type IEnumrable
Maybe this:
tmp = DisplayColumns.ToList();
var res = tmp.Except(tmp.Where(a => a.ColumnName == "Bug" || a.ColumnName == "Feature"));
foreach(var x in res) x.IsSeleceted = true;
Without using foreach
DisplayColumns
.Select(s=> {
s.IsSelected = (s.ColumnName == "Bug" && s.ColumnName == "Feature");
return s;
});

LINQ - FirstOrDefault() then Select()

I have the following LINQ query that fires an exception when the FirstOrDefault() returns null. Ideally I would like to avoid the null check. Is there a way to do this? I wish to return 0 if there are no CPOffsets that satisfy the FirstOrDefault() call.
double offset = OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime).CPOffset;
The only way I can see to achieve this is the following:
CPOffset cpOffset = OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime);
double offset = cpOffset != null ? cpOffset.CPOffset : 0;
Is there another more succinct way? Using Select() after the FirstOrDefault() doesn't compile but I thought might be appropriate here?
I think this should work, I'm not near by VS to check it out...
OrderedOffsets.Where(o => o.OffsetDateTime > cpTime).Select(x => x.CPOffset).FirstOrDefault();
DefaultIfEmpty can be used to ensure that the collection always has at least one element.
double offset = OrderedOffsets.Where(o => o.OffsetDateTime > cpTime)
.Select(o => o.CPOffset)
.DefaultIfEmpty()
.First();
I think a good pattern could be :
double offset = (OrderedOffsets.FirstOrDefault(o => o.OffsetDateTime > cpTime) ?? someDefaultObject).CPOffset;
with someDefaultObject an object holding default values... With this pattern, you can change easily you default values through your code !
If OrderedOffsets can be a struct you could also just put your default value there ! :)

Is there an opposite of LINQ's All method?

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))

Categories