3

I have looked up some orderby examples but I'm still confused about the best linq expression to sort the assembly in the code to produce this list:

Level Parent      Child  
1     L010057501U 231-100-002  
1     L010057501U 307-355-022  
2     307-355-022 307-355-058  
3     307-355-058 355-100-008  
3     307-355-058 357-200-002  
2     307-355-022 307-355-059  
3     307-355-059 355-200-005  
3     307-355-059 357-100-002  

The results needs to be sorted by level but the child needs to be immediately after the parent before the next parent is listed. The components of the assembly could be several levels deep. I hope I have explained adequately.

    class Program
{
    static void Main(string[] args)
    {
        SortAssembly();
        Console.ReadLine();
    }
    class Assembly
    {
        public int Level { get; set; }
        public string Parent { get; set; }
        public string Component { get; set; }
    }

    private static void SortAssembly()
    {
        Assembly[] assemblies = { 
            new Assembly { Level=1, Parent="L010057501U", Component="231-100-002" },
            new Assembly { Level=1, Parent="L010057501U", Component="307-355-022" },
            new Assembly { Level=2, Parent="307-355-022", Component="307-355-058" },
            new Assembly { Level=2, Parent="307-355-022", Component="307-355-059" },
            new Assembly { Level=3, Parent="307-355-058", Component="355-100-008" },
            new Assembly { Level=3, Parent="307-355-059", Component="355-200-005" },
            new Assembly { Level=3, Parent="307-355-059", Component="357-100-002" },
            new Assembly { Level=3, Parent="307-355-058", Component="357-200-002" }
        };

        var query = ???  

        foreach (var part in query)
        {
            Console.WriteLine("{0} - {1} - {2}", part.Level, part.Parent, part.Component);
        }
    }
}

1 - L010057501U - 231-100-002
1 - L010057501U - 307-355-022
____2 - 307-355-022 - 307-355-058
________3 - 307-355-058 - 355-100-008
________3 - 307-355-058 - 357-200-002
____2 - 307-355-022 - 307-355-059
________3 - 307-355-059 - 355-200-005
________3 - 307-355-059 - 357-100-002

I tried to implement the IComparable but I'm not grasping it. Still need help on this.

smarsha
  • 99
  • 2
  • 7
  • Please add sample input/output. If 2-3 values are enough to illustrate the question, there is no need to put more. – Victor Zakharov Nov 16 '14 at 00:03
  • possible duplicate of [Recursive Hierarchy - Recursive Query using Linq](http://stackoverflow.com/questions/20974248/recursive-hierarchy-recursive-query-using-linq) – Gert Arnold Nov 23 '14 at 21:45

2 Answers2

2

you can try the following

using System;
using System.Linq;


    public class Assembly
    {
        public int Level { get; set; }
        public string Parent { get; set; }
        public string Component { get; set; }
        public bool Visited{get;set;} // to track visited levels
    }
public class Program
{
    public static void Main()
    {
                Assembly[] assemblies = { 
            new Assembly { Level=1, Parent="L010057501U", Component="231-100-002" },
            new Assembly { Level=1, Parent="L010057501U", Component="307-355-022" },
            new Assembly { Level=2, Parent="307-355-022", Component="307-355-058" },
            new Assembly { Level=2, Parent="307-355-022", Component="307-355-059" },
            new Assembly { Level=3, Parent="307-355-058", Component="355-100-008" },
            new Assembly { Level=3, Parent="307-355-059", Component="355-200-005" },
            new Assembly { Level=3, Parent="307-355-059", Component="357-100-002" },
            new Assembly { Level=3, Parent="307-355-058", Component="357-200-002" }
        };
        DisplayAssemblies(assemblies);

    }

    private static void DisplayAssemblies(Assembly[] data)
    {
        // order the data to be sorted by levels
        var levels=data.OrderBy(t=>t.Level);
        foreach(var level in levels)
            if(!level.Visited)
                DisplayLevel(level,data);

    }

    private static void DisplayLevel(Assembly level, Assembly[] data)
    {
        var childs=data.Where(t=>t.Parent==level.Component).ToArray();
        Console.WriteLine("{0} - {1} - {2}", level.Level, level.Parent, level.Component);
        level.Visited=true;
        foreach(var child in childs)
        {       
            DisplayLevel(child,data);
        }
    }
}

OUTPUT:


1 - L010057501U - 231-100-002
1 - L010057501U - 307-355-022
2 - 307-355-022 - 307-355-058
3 - 307-355-058 - 355-100-008
3 - 307-355-058 - 357-200-002
2 - 307-355-022 - 307-355-059
3 - 307-355-059 - 355-200-005
3 - 307-355-059 - 357-100-002

here a Live DEMO

hope this will help you

Monah
  • 6,714
  • 6
  • 22
  • 52
  • @GertArnold I edited the solution for descending order and check the demo – Monah Nov 23 '14 at 21:35
  • @GertArnold you need a recursive function to display, sorry i didn't look in detailed way to your question – Monah Nov 23 '14 at 21:42
  • @GertArnold kindly check the answer and see the demo, i corrected it now – Monah Nov 23 '14 at 22:04
  • this solution will solve the problem, but what if he needs it with Linq? it can be solved with linq? i will favorite this question to see the answer, i am interested about it – Monah Nov 23 '14 at 22:10
  • Yes this does work. Much appreciated. I would also be interested in a Linq solution. – smarsha Nov 24 '14 at 15:21
0

Have your Assembly class implement IComparable which allows you to define how they are ordered by implementing its only method: CompareTo()

I THINK you were saying that you need to order first by Level, then Parent, then Component. If so you could use something like this:

class Assembly:IComparable
{
    public int Level { get; set; }
    public string Parent { get; set; }
    public string Component { get; set; }

    public int CompareTo(object obj)
    {
        var other = obj as Assembly;

        if (this.Level != other.Level)
        {
            return this.Level.CompareTo(other.Level);
        }

        if (this.Parent != other.Parent)
        {
            return this.Parent.CompareTo(other.Parent);
        }

        return this.Component.CompareTo(other.Component);
    }
}

But, if I have misunderstood your logic, then the idea is to have CompareTo() return a positive integer if this comes before other and a negative integer if other comes before this (or 0 if they are of equal rank).

Once you have IComparable implemented you can just do:

query = assemblies.OrderBy(a => a);

in order to sort the Assemly objects by your own custom ordering

Stewart_R
  • 13,764
  • 11
  • 60
  • 106
  • Actually you dont HAVE to implement `IComparable` on your class at all - you could just use a static or extension method or something and have your lambda expression call it but, imo, from a design point of view it seems sensible to implement it on the class you're comparing instances of in order to acheive the ordering – Stewart_R Nov 16 '14 at 00:28
  • Can you enlighten me on how I would get the sort results listed above? I hope I have illustrated that I need the results nested by Parent/Child before the next parent. – smarsha Nov 18 '14 at 15:56