brian4342
brian4342

Reputation: 1253

Lambda expression to return one result for each distinct value in list

I currently have a large list of a class object and I am currently using the following lambda function to return elements that meet the condition.

var call = callList.Where(i => i.ApplicationID == 001).ToList();

This will return a list of objects that all have an id of 001.

I am now curious as to what different ApplicationIDs there are. So I would like a lambda function that will look into this list and return a list where all the element have a different ApplicationID but only fetches one of those.

Upvotes: 4

Views: 38085

Answers (4)

heq
heq

Reputation: 412

There is a way to use the Distinct in the query, but it makes you take care about the values equality. Let's assume your type is called CallClass and try:

class CallClass : IEqualityComparer<CallClass>
{

    public int ApplicationId { get; set; }

    //other properties etc.

    public bool Equals(CallClass x, CallClass y)
    {
        return x.ApplicationId == y.ApplicationId;
    }

    public int GetHashCode(CallClass obj)
    {
        return obj.GetHashCode();
    }
}

Now you're able to query values distinctly:

var call = callList.Distinct().ToList();

Upvotes: 1

Martijn
Martijn

Reputation: 12102

You are saying

I am now curious as to what different ApplicationIDs there are. So I would like a lambda function that will look into this list and return a list where all the element have a different ApplicationID but only fetches one of those.

I would suggest that is never something you'd actually want. You either don't care about the elements, you care about all of them, or you care about a specific one. There are few (none?) situations where you care about a random one from the list.

Without knowing about which specific one you care, I can't give you a solution for that version. Allesandro has given you a solution for the random one.

When you only care about the distinct ID's you would end up with

callList.Select(c => c.ApplicationID).Distinct()

which just gives you all ApplicationIDs.

if you care about all of them, you'd end up with

callList.GroupBy(c => c.ApplicationID)

this will give you an IEnumerable<IGrouping<String, Thingy>> (where Thingy is the type of whatever the type of elements of callList is.)

This means you now have a collection of ApplicationID -> collection of Thingy's. For each distinct ApplicationID you'll have a "List" (actually IEnumerable) of every element that has that ApplicationID

If you care for the Thingy of that - for example - has the lowest value of property Foo you would want

callList.GroupBy(c => c.ApplicationID)
        .Select(group => group.OrderBy(thingy => thingy.Foo).First()))

here you first Group them by ApplicationID, and then for each list of thingies with the sample ApplicationID you Select the first one of them if you Order them by Foo

Upvotes: 1

Macs Dickinson
Macs Dickinson

Reputation: 987

You can use either First or FirstOrDefault to get back one result

var call = callList.First(i => i.ApplicationID == 001);

If no call exisrs with an ApplicationID of 001 this will throw an exception. If this may be expected consider using:

var call = callList.FirstOrDefault(i => i.ApplicationID == 001);

Here null will be returned if no such call exists and you can handle accordingly in you code.

To find out what other ApplicationId's exist you can query:

var Ids = callList.Where(i => i.ApplicationID != 001).Select(i => i.ApplicationID).Distinct();

Upvotes: 1

Alessandro D&#39;Andria
Alessandro D&#39;Andria

Reputation: 8878

If i understand your question you can try:

var list = callList.GroupBy(x => x.ApplicationID).Select(x => x.First()).ToList();

So if you have a list like:

AppID:1, AppID:1, AppID:2, AppID:2, AppID:3, AppID:3

Will return:

AppID:1 AppID:2 AppID:3

Upvotes: 23

Related Questions