2016-06-13 5 views
-2

私のオブジェクトは、次のようなものになります。アイテムの親子関係に従って階層的にリストを並べ替えるにはどうすればよいですか?

public class Transaction 
{ 
    long Id; 
    long Amount; 
    DateTime Date; 
    string ReferenceNumber; 
    string ParentReferenceNumber; 
} 

それはすでにDateによって並べ替えに来ているが、しかし、私は何をする必要があることは、これらのトランザクションのリストを配置しているので、それらの他の上ReferenceNumberに一致するParentReferenceNumberを持ちますTransactionは、「親と子」の順に表示されます。

これは私が試みたものです。 「コレクションが変更されたため、列挙操作が実行されない可能性があります」というエラーが生成されます。それは私が恐れていたことなので、疑問です。

foreach (var p in Model.PaymentInfo) 
{ 
    var child = Model.PaymentInfo.SingleOrDefault(x => x.ParentReferenceNumber == p.ReferenceNumber); 

    if (child != null) 
    { 
     var parentIndex = Model.PaymentInfo.IndexOf(p); 
     var childIndex = Model.PaymentInfo.IndexOf(child); 
     Model.PaymentInfo.RemoveAt(childIndex); 
     Model.PaymentInfo.Insert(parentIndex + 1, child); 
    } 

} 
+0

あなたがそれをループしているときには、コレクションからアイテムを削除することはできません。しかし、これをもう一度見て、あなたはそれを考えていません。選択したグループにグループを追加し、グループバイに注文してください。そうすれば、余分なコードを必要とせずに望むものが得られます。 –

答えて

0

これを簡単な方法で実装するには、新しいリストを作成する必要がありました。私はクライアントの既存のオブジェクト構造を変更したくなかった。ここで私はそれを達成した方法です:

var sortedList = new List<Transaction>(); 

foreach (var p in ListOfTransactions) 
{ 
    if (sortedList.Contains(p)) 
    { 
     continue; // Don't add duplicates 
    } 

    sortedList.Add(p); // Add the transaction 

    var child = ListOfTransactions.SingleOrDefault(x => x.ParentReferenceNumber == p.ReferenceNumber); 

    if (child != null) // Add the child, if exists 
    { 
     sortedList.Add(child); 
    } 
} 
-1

オブジェクトの並べ替えに関する情報を探しています。詳細はこちらをご覧ください。各ノードに子のリストを追加することにより、 http://www.codeproject.com/Tips/761292/How-to-sort-an-object-list-in-Csharp

list.Sort(delegate(Member x, Member y) 
{ 
    // Sort by total in descending order 
    int a = y.Total.CompareTo(x.Total); 

    // Both Member has the same total. 
    // Sort by name in ascending order 
    a = x.Name.CompareTo(y.Name); 

    return a; 
}); 
+0

これはシンプル(シーケンシャル)ソートではありません。意図したとおりにソートするには、異なるオブジェクトの異なるプロパティを一致させる必要があります。 – 333Matt

+0

あなたが記事を読んでいないことは明らかです。私がちょうどあなたに与えたサンプルは、あなたが尋ねたものとまったく同じです。これは、一致するプロパティ値の降順で並べ替えられたリストを提供します。残りのコードを外挿することができるはずです。 –

0

スタート。その後

public class WorkingTransaction 
{ 
    public Transaction Details; 
    public List<WorkingTransaction> Children; 
    public bool HasParent; 
} 

IdをキーWorkingTransactionsの辞書を、作成します。たとえば。ここでは、transactionsがソートされたトランザクションのリストです。今

var workDict = transactions 
    .Select(t => new WorkingTransaction 
     { 
      Details = t, 
      Children = new List<WorkingTransaction, 
      HasParent = false 
     }) 
    .ToDictionary(t => t.Details.Id, t); 

、辞書を通過し、子どもたちの親のリストに親の参照を持っているものを追加し、HasParentフラグを更新します。同時に、親を持たない項目は「ルートレベル」リストに追加されます。今

List<WorkingTransaction> rootParents = new List<WorkingTransaction>(); 

foreach (var kvp in workDict) 
{ 
    WorkingTransaction parent; 
    if (workDict.TryGetValue(kvp.Value.Details.ParentReferenceNumber, out parent) 
    { 
     parent.Children.Add(kvp.Value); 
     kvp.Value.HasParent = true; 
    } 
    else 
    { 
     rootParents.Add(kvp.Value); 
    } 
} 

、あなたは子供たちのそれぞれの両親とプロセスのそれぞれを通過することができます。

foreach (var t in rootParents) 
{ 
    processChildren(t.Children); 
} 

void ProcessChildren(WorkingTransaction t) 
{ 
    t.Children = t.Children.OrderBy(child => child.Details.Id).ThenBy(child => child.Details.Date); 
    // and recursively process the children of this transaction 
    foreach (var child in t.Children) 
    { 
     ProcessChildren(child); 
    } 
} 

あなたが適切な順序で出力するように子供たちを同様の再帰的な方法を使用することができます。

関連する問題