I have a class that wraps a List and adds functionality for dealing with ratios. It needs to be sorted two ways at different times; by ordinal position, and by the amount of the ratio.
Below is the method I am currently using to do the sort by ordinal position which I want to use as the basis for two related questions:
- Is there a more perfomant way to do this?
- How would I do this using an IComparer?
The primary motivation for passing in the IComparer would be to allow for different implementations to randomly shuffle the list. This post seems to address the same issue but without any resolution in code that I can see. I’m looking for some sample code and usage of it so I can wrap my head around it.
Cheers,
Berryl
/// <summary>
/// Maintains a list of ratios suitable for use in an allocation when the
/// sum of all items is exactly equal to one (100%). No individual it may
/// be less than zero or greater than one.
/// </summary>
public class RatioBag : IList<RatioAssociation>
{
private readonly IList<RatioAssociation> _items = new List<RatioAssociation>();
private Random _rnd;
public void Order(IndexOrdering ordering) {
IList<RatioAssociation> ordered = null;
switch (ordering)
{
case IndexOrdering.FirstToLast:
break;
case IndexOrdering.LastToFirst:
ordered = this.Reverse().ToList();
break;
case IndexOrdering.Random:
if (_rnd == null) _rnd = new Random();
ordered = Enumerable.Range(0, Count)
.OrderBy(x => _rnd.Next())
.Select(index => this[index])
.ToList();
break;
default:
throw new ArgumentOutOfRangeException("ordering");
}
if (ordered == null) return;
Clear();
foreach (var ra in ordered) {
Add(ra);
}
}
The performance of your approach is not optimal, because you aren’t doing an in place sort. Instead you are copying each item twice. First in the call to
ToListand then in the call toAdd.The
IComparerinterface is used in combination with theList.Sortmethod that does an in place sort. So that should be the way to go.You would first need to change the type of
_itemstoList<RatioAssociation>.For each ordering you want to support, you would need to create a new class that implements
IComparer. If these classes wouldn’t be used else where you could put them as private classes insideRatioBag.Your
Ordermethod would then look something like this:However, I would suggest to remove the
IndexOrderingenum and provide one ordering method per ordering type. The code would be cleaner.