Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difficulty understanding particular lambda expression

Tags:

c#

lambda

linq

This is a really simple question, I would imagine, for someone who knows lambda well. I am just now learning it and have run across one expression that doesn't make sense to me.

From what I understand, lambda expressions pass in the variable specified on the left side and runs the code on the right. For instance

myFunction = x => x + x;

so myFunction(2) would return 4.

Anyhow, I was looking at a linq query on here and saw this:

IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);

The n => n ... what does that do? Why not just say OrderBy(n)? All you are doing it passing n into a function that just returns n. >_> What's happening here?

like image 986
user1548103 Avatar asked Oct 21 '25 12:10

user1548103


2 Answers

The n => n ... what does that do?

It just maps any value to itself. It's an identity function.

Why not just say OrderBy(n)?

Because n isn't a variable in scope - it wouldn't be valid to call it like that. That's not a lambda expression, so it would just try to use n as a normal method argument.

Your code is just trying to say "order this sequence by the whole of each element" rather than projecting each element to some other value, but there's no way of saying that directly.

OrderBy requires a projection from the element type to the ordering key type - it's just that in this case we want the identity projection.

You could write your own extra extension method:

public static IEnumerable<T> OrderNaturally<T>(this IEnumerable<T> source)
{
    return source.OrderBy(item => item);
}

And then change your original statement to:

IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderNaturally();

if you found that more readable.

Alternatively, you could create a Functions class with some useful static readonly fields:

public static class Functions<T>
{
    public static readonly Func<T, T> Identity = x => x;
    public static readonly Func<T, T> DefaultValue => x => default(T);
    public static readonly Func<T, string> ToString = x => x == null ? null : x.ToString();
    ...
}

Then:

IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0)
                                    .OrderBy(Functions<int>.Identity)

I don't think I would do that... I'm just suggesting things to think about :)

like image 51
Jon Skeet Avatar answered Oct 23 '25 01:10

Jon Skeet


Let's break this down:

numbers

This is a collection of integers.

.Where(num => num % 2 == 0)

This is saying "find me all items in my collection where my number modulus 2 = 0".

.OrderBy(n => n);

This is then ordering the list. Because the list is of integers, and the specified item is an integer, it will be ordered numerically, lowest to highest.

The reason you need n => n is because you could sort by something other than the value. Say, for example, the length of the item as a string

.OrderBy(n => n.ToString().Length)

Obviously, for integers, this serves no purpose. But for other data types, like classes, this is very helpful.

like image 35
gunr2171 Avatar answered Oct 23 '25 00:10

gunr2171