lwb
lwb

Reputation: 389

How to Split a list into sublists grouping by elements

This is a similar question to This previus question but in my case I don't know how many items I have to put in each list.

I have a Class "Items" with this properties

public class Items{
    public Id { get; set;}
    public String ItemA { get; set;}
    public String ItemB { get; set;}
    public String ItemC { get; set;}
    public String ItemD { get; set;}
    public String ItemE { get; set;}
}
// And a List of Items
List<Items> .... 

This list has these values:

List of Values

How can I Split this List into a new List<List<Items>> Grouping by ItemA and ItemB? In this example the expected result whould be:

List[0] = {1, 10, 20, 30, 40, 50},
          {4, 10, 20, 31, 40, 12}
List[1] = {2, 10, 19, 30, 40, 50}
List[2] = {3, 9, 20, 40, 30, 50},
          {5, 9, 20, 30, 40, 50},
          {6, 9, 20, 41, 40, 12}

Upvotes: 0

Views: 3757

Answers (2)

Rion Williams
Rion Williams

Reputation: 76607

Grouping Made Easy with LINQ

You can take advantage of LINQ's built-in Enumerable.GroupBy() method by supplying an anonymous object to group by :

// This will group your rows using the values in ItemA and ItemB
var grouped = input.GroupBy(i => new { i.ItemA, i.ItemB })
                   .ToList();

This would break your existing collection into the three distinct groupings that you are looking for, each one containing an IEnumerable<Items> that contains each of the ones within that group.

If You Need Integers...

If you wanted to actually retrieve the integer values for your strings (as all of your properties are currently strings), you might consider explicitly parsing them as such or writing a method that will return your expected values as an integer array :

public class Items
{
    // Omitted for brevity

    public int[] ToIntegerArray()
    {
        return new int[]{ 
           Int32.Parse(Id), 
           Int32.Parse(ItemA), 
           Int32.Parse(ItemB), 
           Int32.Parse(ItemC), 
           Int32.Parse(ItemD), 
           Int32.Parse(ItemE) 
        };  
    }
} 

This would allow you to then change your code to only output the actual values as opposed to your collections of Items objects :

// This will group your rows using the values in ItemA and ItemB and map
// each of the inner groupings to an array of integer values
var groupedItems = items.GroupBy(i => new { i.ItemA, i.ItemB }) 
                        .Select(g => g.Select(ig => ig.ToIntegerArray()))
                        .ToList();

Example

enter image description here

You can see a complete working example of this here.

Upvotes: 1

juharr
juharr

Reputation: 32296

Just use GroupBy and create an anonymous class with the properties you want to group on.

var result = yourList.GroupBy(x => new { x.ItemA, x.ItemB })
                     .Select(grp => grp.ToList())
                     .ToList();

Upvotes: 2

Related Questions