C# 如何根据项目';父母/子女关系?
我的对象看起来像这样:C# 如何根据项目';父母/子女关系?,c#,list,C#,List,我的对象看起来像这样: public class Transaction { long Id; long Amount; DateTime Date; string ReferenceNumber; string ParentReferenceNumber; } 它已经按日期排序,但我需要做的是安排这些事务的列表,以便那些具有与另一个事务上的ReferenceNumber匹配的ParentReferenceNumber的事务以“父事务然后子事务”的顺序出现 这是我
public class Transaction
{
long Id;
long Amount;
DateTime Date;
string ReferenceNumber;
string ParentReferenceNumber;
}
它已经按日期
排序,但我需要做的是安排这些事务的列表,以便那些具有与另一个事务
上的ReferenceNumber
匹配的ParentReferenceNumber
的事务以“父事务然后子事务”的顺序出现
这是我试过的。它会产生错误“集合已修改;枚举操作可能无法执行”。这正是我所担心的,因此产生了这个问题
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);
}
}
您正在查找有关对象排序的信息。请查看此处以了解更多信息。
首先向每个节点添加子节点列表。例如:
public class WorkingTransaction
{
public Transaction Details;
public List<WorkingTransaction> Children;
public bool HasParent;
}
现在,浏览字典,将那些具有父引用的项添加到父项的子项列表中,并更新HasParent
标志。同时,任何没有父项的项都会添加到“根级别”列表中
您可以使用类似的递归方法以正确的顺序输出子项。为了以简单的方式实现这一点,我必须创建一个新的列表。我不想更改客户端现有的对象结构。我是如何做到这一点的:
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);
}
}
var sortedList=newlist();
foreach(交易清单中的var p)
{
if(分类列表包含(p))
{
继续;//不添加重复项
}
sortedList.Add(p);//添加事务
var child=ListOfTransactions.SingleOrDefault(x=>x.ParentReferenceNumber==p.ReferenceNumber);
if(child!=null)//添加子级(如果存在)
{
分类列表。添加(子项);
}
}
这不是简单的(顺序)排序。它需要匹配不同对象上的不同属性,以便按预期进行排序。很明显,您没有阅读本文,我刚才给您的示例完全符合您的要求,这将为您提供一个排序列表,其中包含匹配的属性值降序。您应该能够推断代码的其余部分。当您在集合中循环时,您永远无法从集合中删除该项。但是,再看一遍,您已经考虑过了,只需在select中添加一个groupby,然后在groupby上排序即可。这将在不需要大量额外代码的情况下满足您的需求。
var workDict = transactions
.Select(t => new WorkingTransaction
{
Details = t,
Children = new List<WorkingTransaction,
HasParent = false
})
.ToDictionary(t => t.Details.Id, t);
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);
}
}
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);
}
}