Linq query on orderby level then parent and child
I've looked at some ordering examples, but I'm still confused about the best linq expression for sorting an assembly in the code to create 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 must be sorted by level, but the child must be immediately after the parent before the next parent is listed. Assembly components can be on multiple levels. I hope I have explained this properly.
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 IComparable, but I don't understand it. Still need help with this.
source to share
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 is Live DEMO
hope this helps you
source to share
Ask to implement a Assembly
class Assembly
that allows you to define how they are ordered by implementing its single method:CompareTo()
I THINK you said that you need to order first by level, then by parent, then by component. If so, you can 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 misunderstood your logic, then the idea is to CompareTo()
return a positive integer if this
preceded other
and a negative integer if other
preceded this
(or 0
if they are of equal rank).
Once you are done IComparable
, you can simply do:
query = assemblies.OrderBy(a => a);
to sort objects Assemly
by your own order
source to share