Search code examples
c#linqobjecthierarchyrelationships

Transform a parent child structure to child parent


I am working on a project where I need to be able to transform a complex parent child structure to its child parent equivalent, this is necessary as the querying and reporting on the data needs to be possible from either the parent or child pov. This may not make much sense, but here is a simplified version with some sample data:

Lets say I have this data:

base colours (red, blue, green) accent colours (red, yellow, blue)

And I want to transform it to:

red (base colours, accent colours) blue (base colours, accent colours) green (base colours) yellow (accent colours)

It seemed like Linq would be ideal for this but I can't figure it out, I know I could do it a long hand way but it just seems clunky.

So far I have this test class to work against:

class UsageType
{
    public string Usage { get; set; }

    public List<Colour> Colours = new List<Colour>();
}

class Colour
{
    public string Name { get; set; }
}

public class TestClass
{
    public TestClass()
    {
        var usageTypes = new List<UsageType>()
            {
                new UsageType()
                {
                    Usage = "base colours",
                    Colours = new List<Colour>()
                    {
                        new Colour() { Name = "Red"},
                        new Colour() { Name = "Blue"},
                        new Colour() { Name = "Green"}
                    }
                },
                new UsageType()
                {
                    Usage = "accent colours",
                    Colours = new List<Colour>()
                    {
                        new Colour() { Name = "Red"},
                        new Colour() { Name = "Blue"},
                        new Colour() { Name = "Yellow"}
                    }
                }
            };

        var allColours = from clr in usageTypes
                         .SelectMany(ut => ut.Colours, (clr, ut) => new { colour = ut.Name, usage = clr.Usage })
                         select new { clr.colour, clr.usage };
    }
}

What I'd like to know is how to get from my flattened list of colours (the allColours variable in my sample) to having it structured as per my question. Any help on the best way to do this would be appreciated.


Solution

  • GroupBy color will basically give you the desired format:

    var colourUsage =
        from ut in usageTypes
        from c in ut.Colours
        group ut.Usage by c.Name into g
        select new { colour = g.Key, usages = g.ToList() };