Reputation: 2094
I have two List
of the same type Parcel
.
public class Parcel
{
int Id {get;set;}
int RecipientID {get;set;}
DateTime CreatedOn {get;set;}
}
List<Parcel> aparcels = postFacade.GetParcels()
.OrderByDescending(x => x.CreatedOn);
List<Parcel> bparcels = postFacade.GetReplyParcels();
The Parcel
objects from aparcels
are top-level items. Their RecipientID
is never another Parcel
Id.
The Parcel
objects from bparcels
are replies to Parcel
objects in aparcel
. Their RecipientID
is always a Parcel
Id. However bparcels
contains objects all replying Parcel
objects, not just for the list of Parcel
objects in aparcel
.
I want to create a new list of Parcel
objects from aparcels
sorted by CreatedOn
.
However if a Parcel
from aparcels
is referenced by a Parcel
from bparcels
(via RecipientID
) I want to add the corresponding Parcel
from bparcels
after the Parcel
from aparcel
in the list.
I then want to check bparcels
for any other Parcel
objects that reference the "replying" Parcel
and add it to the list, checking bparcels
recursively until no more "reply" Parcel
objects are found.
This is what I've come up with:
List<Parcel> parcels = new List<Parcels>();
var replies = bposts.ToDictionary(u => u.RecipientID, p => p.Id);
foreach (var p in aparcels)
{
parcels.Add(p);
int commid = p.Id;
int val;
while (replies.TryGetValue(commid, out val))
{
parcels.Add(parcelFacade.GetById(val));
commid = val;
}
}
Is there any way I can increase the performance of this operation? It will potentially be dealing with hundreds/thousands of Parcel
objects.
Upvotes: 2
Views: 568
Reputation: 4717
I think you should store a reference to the Parcels themselves in the dictionary, which are already in the list so you don't have to load them again from you Facade, which is probably what is slowing down your code.
List<Parcel> parcels = new List<Parcels>();
var replies = bposts.ToDictionary(u => u.RecipientID);
foreach (var p in aparcels)
{
parcels.Add(p);
Parcel parent = p;
while (replies.TryGetValue(parent.Id, out parent))
{
parcels.Add(parent);
}
}
Or, to make it even shorter:
foreach (var p in aparcels)
{
var current = p;
do parcels.Add(current);
while (replies.TryGetValue(current.Id, out current));
}
Upvotes: 1
Reputation: 165
I think you're overcomplicating things a bit.
You can do a simple loop through the original posts collection, and add in what you need easily by using:
foreach(var a in aposts.OrderByDescending(p => p.CreatedOn))
{
parcels.Add(a);
parcels.Add(bposts.Where(b => a.ID == b.RecipientID).OrderByDescending(p => p.CreatedOn));
}
UPDATE
Taking into account the fact that you want to loop through each bpost reply to get any other replies to it, I've written an iteration method that will loop until all parent -> children -> grandchildren -> etc. are resolved. This should get everything you want based upon created on field.
foreach(var a in aposts.OrderByDescending(p => p.CreatedOn))
{
parcels.Add(a);
foreach(var b in bposts.Where(bpost => bpost.RecipientID == a.ID).OrderByDescending(bpost => bpost.CreatedOn))
{
parcels.AddRange(Iterate(b, bposts));
}
}
public IList<Parcel> Iterate(Parcel a, IList<Parcel> b)
{
var parcels = new List<Parcel>();
foreach(var post in b.Where(bpost => a.ID == bpost.RecipientID).OrderByDescending(bpost => bpost.CreatedOn))
{
parcels.Add(post);
parcels.AddRange(Iterate(post, b));
}
return parcels;
}
Upvotes: 0