LINQ to object query construction

M

michael sorens

After having played around with LINQ and reading the literature on it I have
not been successful in getting this to work so I am looking for some guidance:

I want to find a hunk in a collection whose Start field is the largest in
the collection but less than an arbitrary cutoff ("selectedRow"). The result
of the query should just be that single object of type Hunk. (No two objects
will have the same value for their Start fields.) Here is the code that I
thought might work:

Hunk myHunk =
(Hunk) from h in hunkList
where h.Start < selectedRow
group h by h.Start into g
select g.Max(g2 => g2.Start);

This seems to have two issues:
(1) Runtime error on the cast to Hunk so apparently I am not selecting a
single Hunk.
(2) If I store the result just in a var, the debugger shows me that there
are no objects in the result collection.

To be clear on what I am seeking, here is a SQL-equivalent version of what I
want:

select * from hunkList
where start =
(select max(start) from hunkList
where start < selectedRow)
)

Thanks!
 
J

Jon Skeet [C# MVP]

michael sorens said:
After having played around with LINQ and reading the literature on it I have
not been successful in getting this to work so I am looking for some guidance:

I want to find a hunk in a collection whose Start field is the largest in
the collection but less than an arbitrary cutoff ("selectedRow"). The result
of the query should just be that single object of type Hunk. (No two objects
will have the same value for their Start fields.) Here is the code that I
thought might work:

Hunk myHunk =
(Hunk) from h in hunkList
where h.Start < selectedRow
group h by h.Start into g
select g.Max(g2 => g2.Start);

This seems to have two issues:
(1) Runtime error on the cast to Hunk so apparently I am not selecting a
single Hunk.

You're selecting the maximum value of Start, not the Hunk with the
maximum size. But the result would be an IEnumerable<int> (assuming
Start is of type int - you get the idea) rather than a single int.

(The result of the group ... into g is an
IEnumerable<IGrouping<int,Hunk>> and you're then calling Max on each of
those IGrouping said:
(2) If I store the result just in a var, the debugger shows me that there
are no objects in the result collection.

To be clear on what I am seeking, here is a SQL-equivalent version of what I
want:

select * from hunkList
where start =
(select max(start) from hunkList
where start < selectedRow)
)

I would split it into two parts:

int maxStart = hunkList.Where(hunk => hunk.Start < selectedRow)
.Max(hunk => hunk.Start);

Hunk maxHunk = hunkList.Where(hunk => hunk.Start == maxHunk)
.Single();

(There are alternatives where you could write your own Max method which
returns the element with the maximum projected value, etc.)

Of course, I could have mistaken everything completely - I'm somewhat
tired at the moment. It would help to have an example - could you
produce a short but complete program demonstrating the problem, and
with a small amount of sample data?
 
L

Linda Liu[MSFT]

Thanks Jon for your reply!

Hi Michael,

When we write a query with a group clause (Group by clause as in Visual
Basic), our results take the form of a list of lists. For C#, each element
in the list is an object that has a Key member and a list of elements that
are grouped under that key.

When we iterate over a query that produces a sequence of groups, you must
use a nested foreach loop (For Each as in Visual Basic). The outer loop
iterates over each group, and the inner loop iterates over each group's
members.

In your practice, you needn't use group clause to get what you want at all.
You can filter the items in the collection first and then order the result
descending, and then return the first item. For example:

class Hunk
{
public int Start;
}
List<Hunk> hunkList = new List<Hunk>() { new Hunk { Start = 1 },
new Hunk{Start=2},
new Hunk{Start = 3},
new Hunk{Start=4},
new Hunk{Start=5}};
int selectedRow = 3;

Hunk q = (from h in hunkList
orderby h.Start descending
where h.Start < selectedRow
select h).First<Hunk>();

If you really want to use group clause, the following is a sample:

var q = (from h in hunkList
where h.Start <selectedRow
group h by h.Start into groups
orderby groups.Key descending
select groups).First<IGrouping<int, Hunk>>();

Hunk result;
foreach (var item in q)
{
result = item;
}

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

michael sorens

Thanks to both Jon and Linda--you both provided useful ideas for me.

Follow-up question: could you recommend a good link for learning more about
LINQ? Web searches have revealed various small tutorials but I have not yet
come across a high-quality, comprehensive one.
 
M

Marc Gravell

Which aspect of LINQ?

The later sections in Jon's book ("C# in Depth", Manning) does a pretty
solid job of introducing the main LINQ operations (including an appendix
of the standard LINQ query operators), and the meaning of the language
syntax (since Jon's is a language book). This *mainly* considers
LINQ-to-objects, but touches on the other LINQ uses.

For database work, "LINQ in Action" (also Manning) is a good read; this
book is dedicated to LINQ, so should give you what you want - but it
isn't as detailed in terms of /how/ LINQ works (at the language level etc).

Marc
 
J

Jon Skeet [C# MVP]

Which aspect of LINQ?

The later sections in Jon's book ("C# in Depth", Manning) does a pretty
solid job of introducing the main LINQ operations (including an appendix
of the standard LINQ query operators), and the meaning of the language
syntax (since Jon's is a language book). This *mainly* considers
LINQ-to-objects, but touches on the other LINQ uses.

Just to expand on this a bit, my book takes one chapter to focus on
how query expressions are translated, using LINQ to Objects as an
example, and then another chapter to race through various LINQ
providers.

I'd say it's reasonably comprehensive on the concepts behind LINQ
itself and the C# language support, but does very little if you want
to use LINQ to SQL.
For database work, "LINQ in Action" (also Manning) is a good read; this
book is dedicated to LINQ, so should give you what you want - but it
isn't as detailed in terms of /how/ LINQ works (at the language level etc).

I'd second the recommendation for LINQ in Action.

A couple of other possibilities: C# 3.0 in a Nutshell (by the Albahari
brothers) is very good, and there's also a free ebook by Jamie King
and Bruce Eckel, at http://www.mindviewinc.com/Books/CSharp/Index.php

The latter is very much in an academic textbook style, which suits
some tastes but not others. It's pretty comprehensive though, again
mostly on the language side of things.

Jon
 
L

Linda Liu[MSFT]

Hi Michael,

Thank you for your reply!

For high-quality and comprehensive learning materials for LINQ, see the
following MSDN document:

'Language-Integrated Query (LINQ)'
http://msdn.microsoft.com/en-us/library/bb397926.aspx

Hope this helps.
If you have any question, please feel free to let me know.

Sincerely,
Linda Liu
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 

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