c# - Sorting multiple collections of objects by looking at each object's own path -
this code problem , it's killing me. can't figure out how ... find myself creating temp arrays hold references, loops in loops.. it's mess.
the setup
look @ image. have 3 collections (layers) cross-references between collections.
the goal order somethings indicated arrows. however, c more important b more important (it's bottom-up importance). can change natural order following in different "layer".
so desired order is:
+----+----+----+---+---+---+---+---+----+----+----+---+---+---+---+ | 14 | 15 | 17 | 7 | 8 | 1 | 2 | 9 | 18 | 19 | 12 | 3 | 4 | 5 | 6 | +----+----+----+---+---+---+---+---+----+----+----+---+---+---+---+
you have few times before arrive @ same conclusion. let me break down you.
we start in layer c (c outranks b , a, remember?) ... first column on left start column. have 14, 15 , 17. don't want 18, because 18 not have reference 17. move layer , start @ beginning again 7 , 8. ends there, since 9 not reference 8.
we move 1 layer again , 1 , 2.
then gets difficult -- 2 followed 9, 9 first. see 9 followed 18, grab one. here important part -- c outranks b , a, first 19, go fetch 12 , go layer continue after 2 , 3,4,5,6.
there must ingenieus way , still keep fast. stripped down example. real thing has dozens of objects , layers.
the real thing has virtual propery completes 1-to-many relationship. want avoid property, because adds collection mix, in case make things easier i'll add here.
class { public int id {get;set;} public int followsid {get;set;} public ienumerable<something> followedby {get;set;} }
i renamed properties easier grasp.
you can treat tree structure, , walk left-to-right (or in case, nodes directly linked sublayer prior nodes same layer) ensuring yield current node before navigating sub-nodes...
working code:
public class layer { public string name { get; set; } public int priority { get; set; } public head { get; set; } public add(something s) { if (this.head == null) this.head = s; s.layer = this; this.items.add(s); return s; } public this[int id] { { return this.items.singleordefault(s => s.id == id); } } public list<something> items = new list<something>(); private void buildtree(list<something> list, s = null) { list.add(s); foreach(something ss in s.followers.orderby(sss => sss.layer.priority)) { buildtree(list, ss); } } public list<something> tree { { list<something> list = new list<something>(); if (this.head != null) buildtree(list, this.head); return list; } } } public class { public int id { get; set; } public layer layer { get; set; } public list<something> followers = new list<something>(); public void follows(something s) { s.followers.add(this); } } void main() { layer = new layer() { name="a", priority = 3 }; a.add(new something() { id = 1 }); a.add(new something() { id = 2 }).follows(a[1]); a.add(new something() { id = 3 }).follows(a[2]); a.add(new something() { id = 4 }).follows(a[3]); a.add(new something() { id = 5 }).follows(a[4]); a.add(new something() { id = 6 }).follows(a[5]); layer b = new layer() { name = "b", priority = 2 }; b.add(new something() { id = 7 }); b.add(new something() { id = 8 }).follows(b[7]); b.add(new something() { id = 9 }).follows(a[2]); b.add(new something() { id = 12 }).follows(b[9]); layer c = new layer() { name = "c", priority = 1 }; c.add(new something() { id = 14 }); c.add(new something() { id = 15 }).follows(c[14]); c.add(new something() { id = 17 }).follows(c[15]); c.add(new something() { id = 18 }).follows(b[9]); c.add(new something() { id = 19 }).follows(c[18]); list<something> ordereditems = new list<something>(); list<layer> layers = new list<layer>() { a, b, c }; foreach(layer l in layers.orderby(ll => ll.priority)) ordereditems.addrange(l.tree); }
if run in linqpad, after last line, can:
string.join(",", ordereditems.select(s => s.id.tostring())).dump();
to see output:
14,15,17,7,8,1,2,9,18,19,12,3,4,5,6
Comments
Post a Comment