MyDaftQuestions
MyDaftQuestions

Reputation: 4701

How to group a list with Linq

I have a list which I get from a database. The structure looks like (which I'm representing with JSON as it's easier for me to visualise)

{id:1
value:"a"
},
{id:1
value:"b"
},  
{id:1
value:"c"
},
{id:2
value:"t"
}

As you can see, I have 2 unique ID's, ID 1 and 2. I want to group by the ID. The end result I'd like is

{id:1,
 values:["a","b","c"],
 },
{id:2,
values["g"]
}

Is this possible with Linq? At the moment, I have a massive complex foreach, which first sorts the list (by ID) and then detects if it's already been added etc but this monstrous loop made me realise I'm doing wrong and honestly, it's too embarrassing to share.

Upvotes: 0

Views: 169

Answers (4)

John Wu
John Wu

Reputation: 52290

First convert to a Lookup then select into a list, like so:

var groups = list
    .ToLookup
    ( 
        item => item.ID, 
        item => item.Value
    )
    .Select
    ( 
        item => new 
        { 
            ID = item.Key, 
            Values = item.ToList() 
        } 
    )
    .ToList();

The resulting JSON looks like this:

[{"ID":1,"Values":["a","b","c"]},{"ID":2,"Values":["t"]}]

Link to working example on DotNetFiddle.

Upvotes: 0

Ousmane D.
Ousmane D.

Reputation: 56469

You can group by the item Id and have the resulting type be a Dictionary<int, List<string>>

var result = myList.GroupBy(item => item.Id)
                   .ToDictionary(item => item.Key, 
                           item => item.Select(i => i.Value).ToList());

Upvotes: 3

egnomerator
egnomerator

Reputation: 1115

Just a little more detail to emphasize the difference between the ToLookup approach and the GroupBy approach:

// class definition
public class Item
{
    public long Id { get; set; }
    public string Value { get; set; }
}

// create your list
var items = new List<Item>
{
    new Item{Id = 0, Value = "value0a"},
    new Item{Id = 0, Value = "value0b"},
    new Item{Id = 1, Value = "value1"}
};

// this approach results in a List<string> (a collection of the values)
var lookup = items.ToLookup(i => i.Id, i => i.Value);
var groupOfValues = lookup[0].ToList();

// this approach results in a List<Item> (a collection of the objects)
var itemsGroupedById = items.GroupBy(i => i.Id).ToList();
var groupOfItems = itemsGroupedById[0].ToList();

So, if you want to work with values only after grouping, then you could take the first approach; if you want to work with objects after grouping, you could take the second approach. And, these are just a couple example implementations, there are plenty of ways to accomplish your goal.

Upvotes: 0

AliJP
AliJP

Reputation: 678

You can either use GroupBy method on IEnumerable to create IGrouping object that contains a key and grouped objects or you can use ToLookupto create exactly what you want in result:

yourList.ToLookup(m => m.id, m => m.value);

This creates a hashed collection of keys with their values.
For more information please see below post:
https://www.c-sharpcorner.com/UploadFile/d3e4b1/practical-usage-of-using-tolookup-method-in-linq-C-Sharp/

Upvotes: 2

Related Questions