2

I'm looking for a collection class that will automatically insert elements in sorted order based on a property (namely "Priority"), so that when I iterate over it later, I'll get back the elements in this order.


SortedList seems to sort by keys, which is not what I want.

João Silva
  • 81,431
  • 26
  • 144
  • 151
mpen
  • 237,624
  • 230
  • 766
  • 1,119
  • Did you try SortedDictionary<>? http://msdn.microsoft.com/en-us/library/f7fta44c.aspx – Harvey Kwok Jan 02 '11 at 01:17
  • @Harvey: Also sorts on key. I don't want a key. – mpen Jan 02 '11 at 01:19
  • This statement "SortedList seems to sort by keys, which is not what I want." and your question are contradictions. In order for any kind of sorted order to be imposed there has to be a comparison function (and hence a key to be compared)! Perhaps you want a FIFO queue? – Mitch Wheat Jan 02 '11 at 01:20
  • @Mitch: I think we're confusing terms here. By "key" I'm referring to the thing you place in square brackets to retrieve an item; the indexer. I don't want one of those, that's basically a dictionary. It sounds like you're referring to a sort-key... yes, one of the properties will behave as a "key" to be sorted by, but you won't be able to retrieve the item with this value. If it helps, I'm looking for a `List` that is sorted by `value`. – mpen Jan 02 '11 at 01:40
  • @Mitch: SortedList and SortedDictionary are basically the same except in terms of performance, but neither of them are what I'm looking for. http://stackoverflow.com/questions/935621/whats-the-difference-between-sortedlist-and-sorteddictionary/935631#935631 – mpen Jan 02 '11 at 01:45
  • @Ralph: I'm aware of all those things you mentioned... – Mitch Wheat Jan 02 '11 at 01:54
  • @Mitch: Then you understand how it's not a contradiction? – mpen Jan 02 '11 at 02:00
  • @Ralph: I believe it is a contradiction. You implement IComparable, it uses Priority; Priority is your key field for sorting. – Mitch Wheat Jan 02 '11 at 02:03
  • @Mitch: I feel like we're going in circles here. Yes, priority is the sort-key, but the "key" I'm referring to in the question is a dictionary-key. I want a sort-key, I don't want a dictionary-key. No contradiction. – mpen Jan 02 '11 at 02:25
  • @Ralph: It's your circle!! ;) – Mitch Wheat Jan 02 '11 at 02:26
  • 1
    I know you have got your answer, but from the limited info you have given, it seemed you needed a `TreeBag` from C5, or `OrderedBag` from Power Collections. Passing an appropriate comparer would do. See this [question](http://stackoverflow.com/questions/196512/is-there-a-sorted-collection-type-in-net) – nawfal May 21 '14 at 20:39

3 Answers3

3

You can use a SortedSet<T>, which is new with .NET 4. You can use it on a class that implements IComparable<T> or you can provide an external comparer via a constructor overload. Example:

class Foo
{
    public int Bar { get; set; }
}

class FooComparer : IComparer<Foo>
{
    public int Compare(Foo x, Foo y)
    {
        // add null checking, demo purposes only
        return x.Bar.CompareTo(y.Bar);
    }
}

...

SortedSet<Foo> sortedFoos = new SortedSet<Foo>(new FooComparer());
sortedFoos.Add(new Foo() { Bar = 2 });
sortedFoos.Add(new Foo() { Bar = 1 });

foreach (Foo foo in sortedFoos)
{
    Console.WriteLine(foo.Bar);
}
// Prints 1, 2

Note: This collection behaves like a HashSet<T>. If you add multiple objects that compare equal, they will be discarded.

Anthony Pegram
  • 114,815
  • 25
  • 210
  • 245
  • Seems like what I want. If I implement `IComparable` on the data type, I assume it'll use that? – mpen Jan 02 '11 at 01:22
  • Also, I assume that the sorting is "stable"? -- if two elements are inserted that compare equal, the first one will still be first in the set? – mpen Jan 02 '11 at 01:24
  • @Ralph, yes, it would support `IComparable`. For more information, I would start with the MSDN documentation. http://msdn.microsoft.com/en-us/library/dd412070.aspx – Anthony Pegram Jan 02 '11 at 01:25
  • @Ralph, caution! It looks like this behaves like a `HashSet`, if two items compare equal, the second will be discarded. If you need multiple items with the same key property, you may have to consider another structure. – Anthony Pegram Jan 02 '11 at 01:32
  • @Anthony: Yeah... the "key" property will be repeated, but the object as a whole ought to be unique. I guess it doesn't matter though if it only looks at the Compare function. – mpen Jan 02 '11 at 01:36
  • @Ralph, the `Compare` or `CompareTo` function does not need to only consider one property. You can use as many as you want as tie-breakers, but ultimately, you would need a way to differentiate between them. – Anthony Pegram Jan 02 '11 at 01:43
  • @Anthony: Yeah...but I don't want tie-breakers. In case they have the same priority, I want it to be FIFO. – mpen Jan 02 '11 at 01:47
2

You need a PriorityQueue. You can find several implementations in this similar question: C# Priority Queue.

Community
  • 1
  • 1
João Silva
  • 81,431
  • 26
  • 144
  • 151
  • 1
    Hehe...also my question :) Difference is, this time I don't need the priority separate. – mpen Jan 02 '11 at 01:23
1

C5 has an IntervalHeap that does what I want.

mpen
  • 237,624
  • 230
  • 766
  • 1,119