2016-10-05 7 views
0

私は、学生を定義するクラスを持ち、その学生のすぐ後ろにプロパティ(FollowedBy)を持っています。私は、このリンケージに基づいて学生を注文する方法を探しています。カスタムIComparerを使用してポインタ値で注文する

class Student 
{ 
    public int StudentID { get; set; } 
    public string Name { get; set; } 
    public int? FollowedBy { get; set; } 
} 

var lstStudents = new List<Student>() 
{ new Student() { StudentID = 2, Name = "Mark", FollowedBy =4 }, 
new Student() { StudentID = 1, Name = "Sam", FollowedBy = 2}, 
new Student() { StudentID = 4, Name = "Fred", FollowedBy =null } , 
new Student() { StudentID = 3, Name = "Janice", FollowedBy = 1}}; 

    for (var s in  lstStudents.OrderBy(x => ????)) 
    { 
     console.Write(s.Name); 
    } 

// The output I'm looking for 
// Janice 
// Sam 
// Mark 
// Fred 
+0

[OK]を。私はそれに言い換えるつもりです。 – Aheho

+1

2つの要素を比較するだけで、順序を決定できるかどうかはわかりません。 JaniceとMarkを比較してください。あなたはSamを写真に持たずに誰が最初にいるのかわからないでしょう。 – Aheho

+5

最初はソートを使うのは意味がありません。根ノードを見つけてチェーンに従います。他のグラフのトラバーサルの問題と同様です。これは、ソートとは異なり、O(n)操作です。よりシンプルで高速です。 – Servy

答えて

2
public List<Student> GetOrderedStudents(List<Student> students) 
    { 
     Student[] reverseOrder = new Student[students.Count]; 

     Student last = students.Single(s => s.FollowedBy == null); 

     reverseOrder[0] = last; 
     Student next = last; 

     for (var i = 1; i < students.Count; i++) 
     { 
      next = students.Single(s => s.FollowedBy == next.StudentID); 
      reverseOrder[i] = next; 
     } 

     return reverseOrder.Reverse().ToList(); 
    } 
2

何をしようとしていることは厳密にソートされていない、そしてそれは、セット全体のIComparer意識の実装を行うことなくA > B > C => A > Cのようなcomparitive原則に依存している特定のソートアルゴリズムをサポートしていません。そのようなIComparerは、単純に検索を使用してソートするよりもはるかに遅く実行される可能性があります。

FollowedBy/StudentIDコンボのセットを検索するために独自の仕組みを使ったヘルパーメソッド(linqのような構文を使用する場合は、拡張メソッド)を作成する方が簡単なようです。

+0

要件は、 "後に続く"ノードが*シーケンスの*後の*どこかにあるのではなく、すぐに*それに従うということではなく、実際には明確なシーケンスです(おそらく、伝統的なソートメカニズムを介して生成することができます。 – Servy

+0

私はパフォーマンスについて心配していません。リストは一般的に12ダース未満のアイテムです。 – Aheho

+0

@Servy私はこれを知っていますが、Quicksort(NETで使用される)はすべての可能な比較(O(N^2)の結果)を避け、すべての 'x-after-y'インスタンス? – David

2

あなたはルートを検索し、FollowedBy従うことができます:

Dictionary<int, Student> dict = lstStudents 
    .ToDictionary(item => item.StudentID); 

    // root 
    Student s = dict[lstStudents 
    .Select(item => item.StudentID) 
    .Except(lstStudents 
     .Where(item => item.FollowedBy.HasValue) 
     .Select(item => item.FollowedBy.Value)) 
    .First()]; 

    for (; s != null; s = s.FollowedBy == null? null : dict[s.FollowedBy.Value]) { 
    Console.WriteLine(s.Name); 
    } 
関連する問題