C# - list sorting - x and y - c#

I have this code and I understand that it's sorting the list lstDMV. But please help me break it down.
lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
What does => mean? And how does it work based on the integer returned from the compare function?
How can I sort my lstDMV if I'm sorting integers instead of dates?

It's called lambda expression.
For the comparison itself, do have a look at the DateTime.Compare method. See its return values:
< 0 --> t1 is earlier than t2
0 --> t1 is the same as t2
> 0 --> t1 is later than t2

The lambda operator => in
lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
basically creates a new delegare with a block of code to excecute. The x and y is past along as parameters.
you could sort a list of int by changing the code to
lstDMV.Sort((x, y) => x.CompareTo(y));

It is called lambda operator. From MSDN;
The => token is called the lambda operator. It is used in lambda
expressions to separate the input variables on the left side from the
lambda body on the right side. Lambda expressions are inline
expressions similar to anonymous methods but more flexible; they are
used extensively in LINQ queries that are expressed in method syntax.
For sorting operation, use Sort() method like this;
lstDMV.Sort((int1, int2) => int1.CompareTo(int2));

=> is a lambda expression operator you can think of it as an anonymous function in javascript
in this case
lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
it is creating a function that is being used as the handler for Sort event.
The complier can infer the types of x and y since it knows the defintion of Close delelegate.

First of all, these are Lambda-Expressions.
Now to your question:
=> is an operator that defines the return value.
In your case (x,y) will return the value of DateTime.Compare(x.NotifDate, y.NotifDate).
Now the Sort()- function of your List will somehow sort the List depending on the value of DateTime.Compare(x.NotifDate, y.NotifDate).
Take a look at the MSDN article: http://msdn.microsoft.com/en-us/library/bb397687.aspx
It's very helpful.

(Others have already answered the lambda operator part of your question)
how can i sort my lstDMV if i'm sorting integers instead of dates?
ints.Sort((i1, i2) => i1.CompareTo(i2));

Related

How does this "Sort((x, y) => x.CompareTo(y))" work? [duplicate]

This question already has answers here:
What does the '=>' syntax in C# mean?
(7 answers)
Closed 2 years ago.
Please look at this block of code:
List<int> list = new List<int>();
list.Add(1);
list.Add(6);
list.Add(2);
list.Add(3);
list.Add(8);
list.Sort((x, y) => x.CompareTo(y));
int[] arr = list.ToArray();
foreach (var i in arr)
{
Console.WriteLine(i);
}
I know that when executed, the code above will print the list in ascending order. If I switch the positions of x and y in "x.CompareTo(y)", then the list will be sorted in descending order instead. I know what CompareTo() does, but here how does it work with x and y to decide the order of sorting? what does x and y represent here?
Sort method signature is public void Sort(Comparison<T> comparison), and if you see the declaration of Comparison it is public delegate int Comparison<in T>(T x, T y).
Just see the comments for Comparison.
//
// Summary:
// Represents the method that compares two objects of the same type.
//
// Parameters:
// x:
// The first object to compare.
//
// y:
// The second object to compare.
//
// Type parameters:
// T:
// The type of the objects to compare.
//
// Returns:
// A signed integer that indicates the relative values of x and y, as shown in the
// following table.
// Value – Meaning
// Less than 0 –x is less than y.
// 0 –x equals y.
// Greater than 0 –x is greater than y.
So it does the comparison for all the elements in the order, and if you swap x and y then it will do just the reverse of it.
In simple terms, (x, y) => x.CompareTo(y) is like a one line version of a method - it goes by various names, usually "lambda" or "delegate". You can think of it as a method that is stripped down as much as possible. Here's the full method, I'll talk about stripping it down shortly:
int MyComparer(int x, int y){
return x.CompareTo(y);
}
The list will perform a sort and will call this method every time it wants to make a choice as to which of the two ints it's considering, is larger than the other. How it does the sort is irrelevant, probably quicksort ish, but ultimately it will often want to know whether x is larger, same or smaller than y
You could take that method I wrote up there and call sort with it instead:
yourList.Sort(MyComparer)
So c# has this notion of being able to pass methods round in the same way that it passes variable data around. Typically when you pass a method you're saying "here's some logic you should call when you need to know that thing you want to know" - like a custom sort algorithm trhat you can vary by varying the logic you pass in
In stripping MyComparer down, well.. we know this list is full of ints so we know that x and y are ints, so we can throw the "int" away. We can get rid of the method name too, and because it's just one line we can ditch the curly brackets. The return keyword is unnecessary too because by definition to be useful the single line is going to have to evaluate to something returnable and it shall be returned implicitly. The => separates the parameters from the body logic
(method,parameters) => logic_that_produces_a_value(
So that long winded method can be boiled down to
(x,y) => x.CompareTo(y)
x,y are whatever type the list holds, the result value is a -1, 0 or 1 which list will use to determine how x and y relate sorting wise. They could be called anything; just like when you declare a method MyMethod(int left, int right) and choose to call the parameters "left" and "right", here we do the same because this is just declaring name parameters - you could easily write (left,right) => left.CompareTo(right) and it'd work the same
You'll see it a lot in c#, because c# devs are quite focused on representing logic in a compact fashion. Often the most useful way of making something flexible and powerful is to implement some of the logic but then leave it possible for another dev to finish the logic off. Microsoft implemented sorting into list, but they leave it up to us to decide "which is greater or lesser" so we can supply logic that influences sort order. They just mandated "any time we want to know which way round two things are we'll ask you" - which means they don't need to have SortAscending and SortDescending - we just flip the logic and declare that 10 is less than 9 if we want 10 to come first.
LINQ relies on "supply me some logic" heavily - you might be looking for all ints less than 3 in your list:
myList.Where(item => item < 3)
LINQ will loop over the list calling your supplied logic (lambda) here on every item and delivering only those where your lambda is true. item is one of the list entries, in this case an int. if the list held Person objects, item would be a Person. To that end I'd recommend calling it p or person to make it clearer what it is. This will become important when you start using more complex lambdas like
string[] wantedNames = new [] { "John", "Luke" };
people.Where(p => wantedNames.Any(n => p.Name == n));
This declares multiple names you're looking for then searches the list of people for all those whose name is in the list of wanted names. For every person p, LINQ asks "wantedNames, do Any of your elements return true for this supplied logic" and then it loops over the wantedNames calling the logic you supplied (n, the item from wantedNames is equal to the person name?).
Here you've used two different methods that take custom logic that LINQ calls repeatedly - Where is a method that takes a delegate, and so is Any; the Any operates on the list of names, the Where operates on the list of people so keeping it clear which is a Person p and which is a name string n using variable names is better than using bland names like a and b.
Got more into on your Sort method see the docs:
See List.Sort(Comparer) for more info
https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.sort?view=net-5.0#System_Collections_Generic_List_1_Sort_System_Comparison__0__

C# Linq questions on select parameters

I have the basic understanding of select method in linq.
var arrayIndex = Enumerable.Range(10, 10).ToArray();
This one will create an array with integers 10 to 19.
For some real life problems, I need to use the index of the original data.
After some research, I found that I can do something like this
var multipliedArray = arrayIndex.Select((i, Index) => i * Index).ToArray();
I know that i is the item itself, in this case i will be integer.
So, just two questions
How do I know the full list of parameters that can put within the bracket (like the Index).
What's the other use case for having different parameter in the bracket.
The part within the Select...
(i, Index) => i * Index
...is lambda expression, which is equivalent to an anonymous method. If you would write the method non-anonymously, it would look like this:
int Calculate(int i, int Index) {
return i * Index;
}
When you want to pass a method as an argument, the respective parameter needs to be a delegate that matches the method's signature. The given Calculate nethod and, since they are sharing the same signature, your lambda expression match the signaturee of the Func<int, int, int> delegate. As it turns out, Enumerable.Select<int, int>offers you an overload with exactly this delegate, so you can use your lambda expression. The other (more widely used) overload accepts a Func<int, int>, which is the version without the index. There are no other overloads, so you can not have other arguments in your lambda expression.
For a better understanding, you can refer to the relevant document Or using Code Completion in development environments.

Very simple explanation of a Lambda Expression

I am looking for a very simple - basic - no hardcore programming mumbo jumbo, simply put a generalized overview of a Lambda Expression in layman's terms.
A lambda expression is, simply put, a re-useable expression which takes a number of arguments:
x => x + 1;
The above expression reads "for a given x, return x + 1".
In .NET, this is powerful, because it can be compiled into an anonymous delegate, a nameless function you can declare inline with your code and evaluate to get a value:
int number = 100;
Func<int, int> increment = x => x + 1;
number = increment(number); // Calls the delegate expression above.
However, the real power of a lambda expression is that it can be used to initialize an in-memory representation of the expression itself.
Expression<Func<int, int>> incrementExpression = x => x + 1;
This means that you can give that expression to something like LINQ to SQL and it can understand what the expression means, translating it into a SQL statement that has the same meaning. This is where lambdas are very different from normal methods and delegates, and normally where the confusion begins.
Lambda Expressions are inline functions that have a different syntax to regular functions.
Example Lambda Expression for squaring a number.
x => x * x
A small unnamed inline method. Is that basic enough for you? I'm not sure what you are looking for exactly.
You also said in "layman's" terms - I presume that you have some level of software development experience (so not a complete layman)
In non functional programming languages expressions (that act on variables) perform calculations and they perform those calculations once.
Lambda expressions allow you to define (in an expression) via different syntax code that can work on a list and can conceptually be considered a function.
You could simplify this to say "They let you define functions in expressions".
Does not quite get to the "why". The why is the more interesting, in my opinion. Lambda expression allow for the manipulation of functions and partial functions.

Why does >= work but => not?

When checking if a integer is the same or above a current number.. so I type
if (5 => 6) { //Bla }
but it shows this as a error. Why? Isn't it exactly the same as
if (5 >= 6) { //Bla }
The reason why it does not work is because => is not equivalent to >=.
=> is used in a lambda expression. Like :
(int x, string s) => s.Length > x
I do agree it is annoying. Before lambda expressions I used to get it wrong sometimes. Now I always know that one (=>) is a lambda expression and and other (>=) is the greater than equal to sign
Because the operator is >= not =>.
The writers of the language could have chosen either syntax, but had to choose one. Having two operators meaning the same thing would be confusing at best.
However, the operator is read "greater than or equal to" so it does make sense that the > symbol is first.
Also => is now used for Lambda expressions.
Because => is meant for lambda expressions:
Action<object> print = o => Console.WriteLine(o);
print(123);
Besides, you don't say "equal to or greater than", which is what => would have been pronounced as otherwise.
The confusion here is that you're assuming >= is two operators smooshed together. In fact, it's only one operator with two characters, much the same as tons of other operators (+=, *=, -=, etc).
Why should it be? =! is not the same as != either. This is a part of the languages syntax.
In this specific case, => is also used for lambda expressions so it has another purpose.
Because it is called greater or equal to. Not equal or greater than. Simple uh?
In C# the greater than or less than sign must come BEFORE the equal sign. It is just part of the syntax of the language.
Because => stands for Lambda expressions in c#.
>= stands for greater than or equal to, as you already know.
The syntax is such that you have to use >= while comparing two entities. Also just additionally you can notice that even a space between them will give errors - > =
No, it is not this same. Correct operator in c# is >= for comparission and => for lambda expression.
#Barry's answer is probably the most insightful of the lot here. A single operator does not mean a single character; the fact that > and = combine to form >= does not mean that it's doing both > and =; it's doing a single operation. The fact that the defined operator for that operation includes the characters for two other similar operations is irrelevent.
I suppose if you really wanted to you could override it so that both >= and => worked the same way -- C# does allow operator overrides. But it would be a bad idea because as others have already said, => is actually in use for other purposes.

Is there a quick way to say If notempty x = y else x = default in a Linq where query

Is there a quick way to say
Where (data.x == (If notempty x = y else x = default))
Assuming the data being compared is both strings
Compare listitem.string with passed.string - if passed.string isnotempty, else passed.string equals default value.
in a Linq 'where` query.
Apologies that the question was really badly written.
... As per the comments updated ...
Ok, with your clarifications to the original post, I think I see what you're getting at now.
Try the following clause (where data.x is your current element and y in the passed argument).
where y == (string.IsNullOrEmpty(y) ? "default" : data.x)
I do not believe it's possible to use the null coalescing operator here, since the variables you are comparing and returning are different.
Old Post:
If what is empty? I'm guessing you're referring to y.
For a generic type T, you could use the following clause:
where data.x == (y ?? DefaultValue<T>())
where DefaultValue is a generic function of T that returns a so-called "default" value.
It really depends on the data type of x and y, but say they are strings:
Where (data.x == (!string.IsNullOrEmpty(y) ? y : "default"))
It's called the conditional operator.
Your original post could be interpreted to be this:
where (data.x ?? y) == y
Edit: I am now pretty sure this is what you were attempting. :)
Edit 2: This is the null-coalescing operator.
Edit 3: Whoever voted me down should post a reason. I interpreted the first post as: "If x is not empty, it should equal y, but it's ok to equal default(typeof y)." For reference types or nullable types, my post is correct.
Edit 4: Mine still could be the cleanest answer to his updated post. I keep reading it and it's still strangely worded. The (string.IsNullOrEmpty(y)) post is the other possibility.

Categories