Juan Carlos Oropeza
Juan Carlos Oropeza

Reputation: 48177

LINQ How retrieve anonymous property

I have an array of integers. I can GroupBy, Sort, and Take the less repeat element:

int [] list = new int[] {0, 1, 1, 0, 2};
var result = list
    .GroupBy(a => a)
    .Select(g => new {
        Number = g.Key,
        Total = g.Count()
    })
    .OrderBy(g => g.Total).Take(1);

Inside a foreach I can retrieve the result, I even have Intellisense for group properties {Number, Total}

foreach (var group in result)
{
    // Display key and its values.
    Console.WriteLine("Number = {0} Total: {1}", group.Number, group.Total);
}

But I don't like to do a foreach to do that, I prefer to do something like

result.Number or 
result[0].Number

But doesn't work. What should be the right way to do it?

Upvotes: 0

Views: 108

Answers (4)

Marco
Marco

Reputation: 23927

An anonymous type does not implement IEnumerable<T>, there for you cannot access it via index.

If you only want the very first object you can use First() or FirstOrDefault. If you cast it to an array, you can use an index and then have support for your properties again:

result.FirstOrDefault().Number;
result.ToArray()[1].Number;

enter image description here

Upvotes: 1

Rahul Singh
Rahul Singh

Reputation: 21795

Your problem is that Take returns IEnumerable, so if you want to fetch only first element, in that case use FirstOrDefault:-

var result = list.GroupBy(a => a)
                        .Select(g => new
                        {
                            Number = g.Key,
                            Total = g.Count()
                        })
                        .OrderBy(g => g.Total).FirstOrDefault();

Then, you can simply say: - result.Number. Please note FirstOrDefault may return null so better check for nulls before accessing any property otherwise you may get Null Reference Exception.

Also, if you are looking for any specific index then you can use ElementAtOrDefault like this:-

var result = list.GroupBy(.....)..OrderBy(g => g.Total);
int SecondNumber = result.result.ElementAtOrDefault(1).Number;

But again be aware of NRE.

Upvotes: 2

0xDEADBEEF
0xDEADBEEF

Reputation: 3431

Check these Methods:

.FirstOrDefault(); //gets the first element
.Take(n); //gets the first n elements
.Skip(n).FirstOrDefault(); //gets the (n+1)th element
.Skip(n).Take(m); //gets the first m elements after n elements 

Upvotes: 1

vcsjones
vcsjones

Reputation: 141588

You are using Take(1) which still returns an IEnumerable. You probably want to use FirstOrDefault() which does not return an IEnumerable.

.OrderBy(g => g.Total).Take(1);

Then you can use it like result.Number and result.Total.

Upvotes: 2

Related Questions