tags:

views:

228

answers:

3

I'm trying to get the n-th element out of a list of anonymous types returned by a LINQ query where n is a random number from 0 to 100. Messed around with it a while now and I'm not getting anywhere. My code (with names changed to protect IP):

var query = from Table1 t1 in theContext.Table1 
   join Table2 t2 in theContext.Table2
    on ... 
    where ... 
   select new 
   {
       partNum = t1.part_number, 
       partSource = t2.part_source
   }

int num = new Random().Next(0, 100); 

// here's where the code I've tried fails

Can I somehow do a Take<T>(100).ToList<T>()[num] to get a single anonymous type with partNum and partSource? I ended up solving this by explicitly defining a type, but it seemed like I was missing a more elegant solution here. All I want to do is return a Dictionary<string, string> to the caller so I'd prefer not to have to define a type outside of this method.

Update: ElementAt doesn't work for this. I tried adding:

// get a random part from the parts list
int num = new Random().Next(0, query.Count() - 1 );
var nthElement = query.ElementAt(num);

And I got an exception: The query operator 'ElementAt' is not supported.

+6  A: 

You should be able to use:

var item = query.Take(100).ToList()[num];

Of course, it would be more efficient to do:

var item = query.Skip(num).First();
Marc Gravell
Am I missing something here? Doesn't he really just want to use the ElementAt function?
Noldorin
(responded on other reply, for visibility)
Marc Gravell
ElementAt returns: "ElementAt is not supported ... System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc) "
jcollum
Oh lol, in that case Marc's solution may be the one to go with - does that work fine for you?
Noldorin
Ah, Skip! Thanks, I'll try it.
jcollum
My confusion here was that all the intellisense for linq methods like Skip and Take seem to want a type in the <> but it seems that it's optional.
jcollum
@jcollum: It's inferred - that's what of the nice things C# does for you. Anonymous types would be fairly useless without that feature, in fact.
Noldorin
+1 Solved my problem with the NotSupportedException
magnifico
+3  A: 

I believe you just want the ElementAt extension method:

var nthElement = query.ElementAt(num);

No need to mess with Take queries or such, and certainly not ToList.

Noldorin
re your comment on my answer; my first example (Take/ToList) was merely to show how his attempt can be fixed. There isn't much to choose between Skip(...).First() and ElementAt(...), and I've already given you +1 ;-p
Marc Gravell
@Marc: Yeah, I understood you were just correcting his use of Take/ToList. (I was replying purely to his question and not your answer, which I hadn't seen yet.) An indeed, using Skip and First is only barely an unnecessary elaboration...
Noldorin
Nope, I tried ElementAt and it didn't work: "The query operator ElementAt is not supported"
jcollum
Keep in mind that ElementAt is still the best option for LINQ to Objects however. Haven't had any real experience with LINQ to SQL, so I had no idea it didn't work with it.
Noldorin
Got it, thanks.
jcollum
A: 

Marc nailed it, but if you want numbers from 0 to 100 inclusive, you need:

int num = new Random().Next(0, 101);

Because the Next(int, int) function uses an exclusive upper-bound.

John Rasch
If we are taking 100 items, we want an index in [0,99], so Next(0,100) is ideal.
Marc Gravell
Wow... you're 100% right on that. I seem to read certain sentences and then go off on tangents completely unrelated with what he's trying to do. Maybe this will help someone else, who knows
John Rasch
I agree with Marc.
jcollum