What Lambda expression corresponds to this LINQ query?

R

raylopez99

See the // commented out lines below.

This is what I want a query for (in lambda notation).

Basically to order an array of ints from lowest value to highest value
(ascending). I can do this with LINQ, but how to do it with lambda
notation?

RL


int [] intArr = new int[5]{1,22,3,11,14};
IEnumerable<int> myfilteredInts = from n in intArr
where n > 10
select n;
foreach (int i in myfilteredInts)
{ Console.Write("filteredInt: {0} ,", i); }
Console.WriteLine("");
var reverseInts = myfilteredInts.Reverse(); //reverse the
natural sequence
foreach (int i in reverseInts)
{ Console.Write("reverseInts: {0} ,r,", i); }
var orderHighToLow = from n in reverseInts
orderby n descending
select n;
Console.WriteLine("HightoLow");
foreach (int i in orderHighToLow)
{ Console.Write("ordrH->L {0} ,Hl,", i); }
Console.WriteLine("LowtoHigh");

//var orderLowToHigh = from m in orderHighToLow
// orderby m ascending
// select m;

//foreach (int i in orderLowToHigh)
//{ Console.Write("ordrL>>H {0} ,lH,", i); } ////works fine
 
D

Dan Tallent

I'm not sure exactly what your trying to do but something like this will
work

var HighesttoLowest = numbers

..OrderBy(r => r)

..Select(r => r);
 
G

Göran Andersson

raylopez99 said:
See the // commented out lines below.

This is what I want a query for (in lambda notation).

Basically to order an array of ints from lowest value to highest value
(ascending). I can do this with LINQ, but how to do it with lambda
notation?

A lambda expression is a short form to write a delegate, so for example
the lambda expression:

(x, y) => x - y

is the same as:

delegate(int x, int y) { return x - y; }

You could use that so sort an array using the Sort method:

Array.Sort<int>(intArr, (x, y) => x - y);
 
M

Marc Gravell

A lambda expression is a short form to write a delegate

In /this/ case (LINQ-to-Objects): yes - but it could equally be compiled
to an Expression, which is very, very different.

A lambda *statement*, on the other hand, is always a delegate.

Marc
 
J

Jon Skeet [C# MVP]

In /this/ case (LINQ-to-Objects): yes - but it could equally be compiled
to an Expression, which is very, very different.

A lambda *statement*, on the other hand, is always a delegate.

I don't think I've heard "lambda statement" as a term before. I'd
normally say "lambda expression with a statement body" (or even
"statement block body") which is wordier, but still keeps the idea
that the whole thing is an expression which can be converted to
something (in this case, just a delegate).

Jon
 
M

Marc Gravell

hmm... I've checked the spec and you are right... I've heard it used
many times, though - meaning the same thing (i.e. the message as per
CS0384) - and it shows up plenty in searches ("lambda statement" wins in
a Google-fight - not that such is necessarily an indication of correctness).

I shall update my internal dictionary to use the correct terminonlogy ;-p

Cheers,

Marc
 
J

Jon Skeet [C# MVP]

hmm... I've checked the spec and you are right... I've heard it used
many times, though - meaning the same thing (i.e. the message as per
CS0384) - and it shows up plenty in searches ("lambda statement" wins in
a Google-fight - not that such is necessarily an indication of correctness).

I shall update my internal dictionary to use the correct terminonlogy ;-p

It's probably one of those cases where it's worth using the shorthand
when the subject of discussion is something other than lambda
expressions (they just happen to be relevant) but use the more precise
form when you're really talking about lambdas.

(A bit like saying "I'm passing a string to a method" when you're
interested in something other than parameter passing, but "I'm passing
a reference to a string, by value, to a method" when describing
parameter passing in detail. Side note: should it actually be called
"argument passing"? I suspect so...)

Jon
 
R

raylopez99

Thanks Dan Tallent, that worked. But I defy anybody who thinks this
Lambda expression is more logical than the Linq/Sql equivalent.

For example, both the below fragments yield the same thing (a
reordering from lowest to highest valued int) but I cannot understand
why the .orderby (r => r) works to reorder the numbers.

RL

//var orderLowToHigh = from m in orderHighToLow
// orderby m ascending
// select m;
//Console.WriteLine("HightoLow");
//foreach (int i in orderLowToHigh)
//{ Console.Write("ordrL>>H {0} ,", i); }
////works fine (more logical to understand than the below)


var orderLowToHigh = orderHighToLow.OrderBy(r =>
r).Select(r => r);
foreach (int i in orderLowToHigh)
{ Console.Write("L>>H {0} ", i); } //also works to reorder
from low to high!
 
J

Jon Skeet [C# MVP]

Thanks Dan Tallent, that worked.  But I defy anybody who thinks this
Lambda expression is more logical than the Linq/Sql equivalent.

Note that you don't need the Select(r => r). I don't know what you
mean by "the Linq/Sql equivalent". Do you mean "the query expression
equivalent"?
For example, both the below fragments yield the same thing (a
reordering from lowest to highest valued int) but I cannot understand
why the .orderby (r => r) works to reorder the numbers.

It's very simple - it means "order the elements by their own values".
You need to tell OrderBy what to use as the sort key - and "r => r" is
the identity projection. Seems pretty logical to me. It would be nice
to have an InOrder() method or something like that which was
equivalent to OrderBy(x => x) but you could always write that if you
wanted.

Jon
 
R

raylopez99

Jon said:
It's very simple - it means "order the elements by their own values".
You need to tell OrderBy what to use as the sort key - and "r => r" is
the identity projection. Seems pretty logical to me. It would be nice
to have an InOrder() method or something like that which was
equivalent to OrderBy(x => x) but you could always write that if you
wanted.

Simple for you, Maestro! I kind of figured that out, figuring sort
key "r =>r" must do a CompareTo with elements, returning 1 if greater,
0 if equal and -1 if less than, or something like that, but it's not
obvious what.

Now a followup if I may: given this sorted list of 'low to high', how
to reorder from 'high to low'? would it be: ???--use just words if
not easy to do, since I don't think there's an Ascending/Decending
function built in.

Followup 2 (different question): why the below has no effect?

var orderOddOnly = orderLowToHigh.OrderBy(r => r%2!=0);
foreach (int i in orderHToLow2)
{ Console.Write("H>?L {0} ,", i); }

// for a list of ints, that are even in number, it fails to do
anything! even if changed to OrderBy(r => r%2==0); that is, shouldn't
the IEnumerable orderOddOnly only have odd numbers? Why not?

I think lambda notation, unless you're a guru, is much harder than
Linq, which at least, like SQL, is somewhat intuititive.

Back to my coding...(I'm working on an Array.Sort--it's harder than I
thought, getting the IComparer notation right....)

RL
 
M

Marc Gravell

There are .OrderByDescending(...) and .ThenByDescending(...) to match
..OrderBy(...) and .ThenBy(...)

Marc
[C# MVP]
 
J

Jon Skeet [C# MVP]

Simple for you, Maestro!  I kind of figured that out, figuring sort
key "r =>r" must do a CompareTo with elements, returning 1 if greater,
0 if equal and -1 if less than, or something like that, but it's not
obvious what.

I really think it is if you read the docs, to be honest. Note that the
"r => r" isn't *itself* doing the comparison - but OrderBy is calling
the delegate created from that lambda expression for each element.
Now a followup if I may: given this sorted list of 'low to high', how
to reorder from 'high to low'?  would it be: ???--use just words if
not easy to do, since I don't think there's an Ascending/Decending
function built in.

See Marc's response.
Followup 2 (different question): why the below has no effect?

            var orderOddOnly = orderLowToHigh.OrderBy(r => r%2!=0);
           foreach (int i in orderHToLow2)
            { Console.Write("H>?L {0} ,", i); }

// for a list of ints, that are even in number, it fails to do
anything! even if changed to OrderBy(r => r%2==0); that is, shouldn't
the IEnumerable orderOddOnly only have odd numbers?  Why not?

No, it should *order* by odd/even, but contain all of them. However,
you're not displaying orderOddOnly - you're displaying orderHToLow2.
I think lambda notation, unless you're a guru, is much harder than
Linq, which at least, like SQL, is somewhat intuititive.

You don't have to be a guru. You just have to think about it logically
and perhaps have a little more experience than you do at the moment.
Back to my coding...(I'm working on an Array.Sort--it's harder than I
thought, getting the IComparer notation right....)

You might like ProjectionComparer in MiscUtil: http://pobox.com/~skeet/csharp/miscutil
Basically it lets you build an IComparer from a projection, just like
with OrderBy.

Jon
 
R

raylopez99

Jon said:
Jon Skeet [C# MVP] wrote:

Simple for you, Maestro! �I kind of figured that out, figuring sort
key "r =>r" must do a CompareTo with elements, returning 1 if greater,
0 if equal and -1 if less than, or something like that, but it's not
obvious what.

I really think it is if you read the docs, to be honest. Note that the
"r => r" isn't *itself* doing the comparison - but OrderBy is calling
the delegate created from that lambda expression for each element.

What docs? I get my help from books and from you and other Good
Samaritans. I don't have time to read 'docs' written by PhD's in C.Sci
trying to impress their peers.

See Marc's response.

Yeah, that nailed it. For all the ASCI text spilled, it was simply
that .OrderBy is the converse of OrderByDecending. Nuff said.
No, it should *order* by odd/even, but contain all of them. However,
you're not displaying orderOddOnly - you're displaying orderHToLow2.

No, that's not it. I simply forgot to change "orderHToLow2" to
"orderOddOnly"--I did this for clarity. Something else going on, but
for now it's just a mystery since I've got other things to do.
You don't have to be a guru. You just have to think about it logically
and perhaps have a little more experience than you do at the moment.

No, I bet to differ. You have to be a guru. You are a guru. I have a
couple of years on-off C++ coding experience and about 2 solid months
of C# experience, and I know about 80% of what's there to know about
C#, but to get to that last 20% you need to be a guru.* But Linq and/
or writing your own predicate logic methods and using IComparer etc
are good enough for me.

* you don't have to be a guru however to program a decent program IMO.
You might like ProjectionComparer in MiscUtil: http://pobox.com/~skeet/csharp/miscutil
Basically it lets you build an IComparer from a projection, just like
with OrderBy.

Thanks. I might take a look, but frankly such "home grown" solutions
are usually full of mistakes and it's like using training wheels--you
don't ever get to learn how to ride a real bike. But thanks anyway.
I'll look at your library code, since it has some other stuff that
looks interesting.

RL
 
J

Jon Skeet [C# MVP]

What docs?  I get my help from books and from you and other Good
Samaritans. I don't have time to read 'docs' written by PhD's in C.Sci
trying to impress their peers.

The docs for OrderBy etc in MSDN:
http://msdn.microsoft.com/en-us/library/bb534966.aspx

In fact, the page linked above even tells you how to perform an
identity ordering explicitly!
No, that's not it. I simply forgot to change "orderHToLow2" to
"orderOddOnly"--I did this for clarity.  Something else going on, but
for now it's just a mystery since I've got other things to do.

Well if you can't post the code that you're actually running, it's
pretty hard to diagnose the problem.
No, I bet to differ. You have to be a guru.  You are a guru. I have a
couple of years on-off C++ coding experience and about 2 solid months
of C# experience, and I know about 80% of what's there to know about
C#, but to get to that last 20% you need to be a guru.*  But Linq and/
or writing your own predicate logic methods and using IComparer etc
are good enough for me.

I would like to know how you get your 80% figure. You've made various
posts showing fundamental misunderstandings.

There's plenty of space between "where you are" and "guru" - and I
believe that understanding the identity projection lies in that space.
Thanks. I might take a look, but frankly such "home grown" solutions
are usually full of mistakes and it's like using training wheels--you
don't ever get to learn how to ride a real bike.  But thanks anyway.
I'll look at your library code, since it has some other stuff that
looks interesting.

All due respect, I strongly suspect that my home grown solution is
likely to be at least as reliable as what you come up with. It's
pretty simple code, with plenty of unit tests. And hey, you can
examine the code and learn from it anyway.

Jon
 
G

Göran Andersson

raylopez99 said:
I have a
couple of years on-off C++ coding experience and about 2 solid months
of C# experience, and I know about 80% of what's there to know about
C#

The first time around that you think that you know 80%, you know about
20%. Keep programming for full time for a few years, and perhaps you
will get there the second time, when you may actually be correct about
the percentage...

:)
 
R

raylopez99

The first time around that you think that you know 80%, you know about
20%. Keep programming for full time for a few years, and perhaps you
will get there the second time, when you may actually be correct about
the percentage...


OK Goran, thanks. But I think you have, like Jon, too high of a
standard.

learning about dictionaries tonight...I did not realize that a
dictionary is essentially this ordered pair, but with the ability to
use foreach notation--

String[] myArrayAnimal = { "Zebra", "Ant", "Owl",
"Lion" };
int[] myArrayIntAnimal = new int[] { 10, 20, 11, 21 };
Array.Sort(myArrayAnimal, myArrayIntAnimal); //will sort
by name as key, and preserve order--> Ant <-->20, Lion<-->21, etc
//poor man's dictionary, since not really a true
dictionary,since you cannot use single 'foreach' to traverse both
arrays at the same time
//instead, do this:

//instead, do this (non-sorted however)

Dictionary<string, int> dic = new Dictionary<string,
int>() { { "Zebra", 10 }, { "Ant", 20 }, { "Owl", 11 }, { "Lion",
21 } };
//can also use 'var' in lieu of Dictionary<,> on LHS above
//now three ways to enumerate the dictionary:

foreach (KeyValuePair<string,int> kv in dic) Console.WriteLine(kv.Key
+ ";" + kv.Value);
foreach(string s in dic.Keys) Console.Write(s);
Console.WriteLine("");
foreach(int i in dic.Values) Console.Write(i);

/* //also can have a more complicated value as below
Dictionary<int, StudentName> students = new Dictionary<int,
StudentName>()
{
{ 111, new StudentName {FirstName="Sachin", LastName="Karnik",
ID=211}},
{ 112, new StudentName {FirstName="Dina", LastName="Salimzianova",
ID=317, }},
{ 113, new StudentName {FirstName="Andy", LastName="Ruth",
ID=198, }}
};
*/

//to sort above, use SortedDictionary <TKey, TValue>

RL
 
R

raylopez99

The docs for OrderBy etc in MSDN:http://msdn.microsoft.com/en-us/library/bb534966.aspx

In fact, the page linked above even tells you how to perform an
identity ordering explicitly!

OK, if you say so. All I saw was a good example, which I copied into
my library: IEnumerable said:
Well if you can't post the code that you're actually running, it's
pretty hard to diagnose the problem.

Exact! If you cannot, by looking at the above, tell me how to OrderBy
using the modulus %, to return true for an even number and filter a
list of ints, then it's harder than I thought. Point conceded.
I would like to know how you get your 80% figure. You've made various
posts showing fundamental misunderstandings.

No I did not Jon. Nothing "fundamental" about my misunderstandings.
They are largely trivial if anything.
There's plenty of space between "where you are" and "guru" - and I
believe that understanding the identity projection lies in that space.

I beg to differ.
All due respect, I strongly suspect that my home grown solution is
likely to be at least as reliable as what you come up with. It's
pretty simple code, with plenty of unit tests. And hey, you can
examine the code and learn from it anyway.

Jon

OK I will, thank you. I am curious about the "rand" stuff, since I am
going to do an extinction predictor for estimating when a species goes
extinct, which follows a 'broken stick' model: take a stick, randomly
break it somewhere, then break the smaller piece again randomly, etc,
then do a histogram of the lengths of the stick. Need a good random
number generator, though I don't see why the standard library rand was
not good enough for you.

RL
 
J

Jon Skeet [C# MVP]

raylopez99 said:
OK, if you say so. All I saw was a good example, which I copied into
my library: IEnumerable<Pet> query = pets.OrderBy(pet => pet.Age);

In "Remarks":

"To order a sequence by the values of the elements themselves, specify
the identity function (x => x in Visual C# or Function(x) x in Visual
Basic) for keySelector."
Exact! If you cannot, by looking at the above, tell me how to OrderBy
using the modulus %, to return true for an even number and filter a
list of ints, then it's harder than I thought. Point conceded.

No, it's not harder than you thought. You posted some code, I told you
what's wrong with what you posted, and you replied that that wasn't
your real code. You've failed to post your real code. (Admittedly your
projection returns true for odd numbers, not even ones.)

Here is a short but complete program ordering all the even numbers
first, then all the odd ones (within the range 0-9):

using System;
using System.Linq;

public class Test
{
static void Main()
{
var orderByParity = Enumerable.Range(0, 10)
.OrderBy(r => r%2!=0);

foreach (int x in orderByParity)
{
Console.WriteLine(x);
}
}
}

Note that *ordering* isn't *filtering*. If you want to only show the
odd values, you need to use Where rather than OrderBy.
No I did not Jon. Nothing "fundamental" about my misunderstandings.
They are largely trivial if anything.

You didn't understand what declaring a variable meant. You thought it
was a forward declaration of a class. That's pretty fundamental. You
believed that GUI applications were so completely different to console
apps that they would handle parameter passing differently. Those two
are just off the top of my head. I'm sure you don't really want me to
go back and find all the other misunderstandings.
I beg to differ.

I've seen plenty of people understand lambda expressions, order-by
projections etc with no problem. I certainly wouldn't say that all of
them are "gurus".
OK I will, thank you. I am curious about the "rand" stuff, since I am
going to do an extinction predictor for estimating when a species goes
extinct, which follows a 'broken stick' model: take a stick, randomly
break it somewhere, then break the smaller piece again randomly, etc,
then do a histogram of the lengths of the stick. Need a good random
number generator, though I don't see why the standard library rand was
not good enough for you.

Assuming you mean StaticRandom, you'll see that it uses the standard
library's random number generator anyway. It just does so in a way
which makes it threadsafe.
 
J

Jon Skeet [C# MVP]

raylopez99 said:
learning about dictionaries tonight...I did not realize that a
dictionary is essentially this ordered pair, but with the ability to
use foreach notation--

Another misunderstanding. A dictionary is *not* an ordered pair. It's a
mapping. The point of a dictionary is to be able to efficiently map
from key to value. Most implementations (such as Dictionary) do not
preserve any particular ordering. (Those which do generally have poorer
performance characteristics, as they have more work to do.)
 
G

Göran Andersson

raylopez99 said:
OK Goran, thanks. But I think you have, like Jon, too high of a
standard.

Or perhaps you are using a different scale? Using your scale, is it that
I might know about 300% of what's there to know about C#?
learning about dictionaries tonight...I did not realize that a
dictionary is essentially this ordered pair, but with the ability to
use foreach notation--

Although the dictionary is ordered in some way, it's not useful. The
ordering is based on a modulo of the hash code and the order that the
items were added to the dictionary, so it's not easily predictible.
Besides, this ordering isn't defined in the documentation, you can't
rely on the implementation staying exactly the same in future versions
of the framework.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top