2

I have an array of objects that I sort by type. Within that array is a set of objects of one type that are already in their preferred relative order. After the sort, these objects are grouped together, but no longer in the same order. I am using the sort a follows

Array.Sort(shapes, GetVisualComparer());

I have looked for a sort method that promises to preserve original order, but have found nothing.

I will note that I have a workaround, but it adds unnecessary confusion to the code, and does not address the general problem if it comes up in the future.

7
  • 2
    " a sort method that promises to preserve original order" Huh? "adds unnecessary confusion" I know what you mean... please show sample data and a desired result. Commented Aug 13, 2013 at 22:08
  • 1
    You will have to imbue the comparer with information regarding the existing order of those items so that it can keep them in the same order. A workaround would be to sort everything but these items and insert the pre-sorted group at the desired point afterwards, but that's probably going to be more clunky. Commented Aug 13, 2013 at 22:09
  • Why don't you use 'group by' first, and then sort the 'group by' list? Commented Aug 13, 2013 at 22:11
  • Jon, that is exactly what I did, it is ugly. Commented Aug 13, 2013 at 22:11
  • GroupBy preserves the order, that is guaranteed. "The IGrouping<TKey, TElement> objects are yielded in an order based on the order of the elements in source that produced the first key of each IGrouping<TKey, TElement>. Elements in a grouping are yielded in the order that the elements that produced them appear in source." Commented Aug 13, 2013 at 22:13

2 Answers 2

2

Make a copy of the original array. Then, make your comparer compare the original indexes of your elements if their type is equal.

I don't know on what you base your type sorting, but sorting by name, it would look somewhat like this:

public class TypeComparer : IComparer<Type>
{
    public int Compare(Type x, Type y)
    {
        int result = StringComparer.InvariantCulture.Compare(x.Name, y.Name);
        if (result == 0)
        {
            result = Array.IndexOf(originalArray, x).CompareTo(Array.IndexOf(originalArray, y));
        }
        return result;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

well, it looks good, but then you end up performing 2 more linear searches of the array on every equals comparison. That could completely destroy the performance of the sort itself... with an array full of dups, this is like N^2 plus the cost of the sort, isn't it?
Unless that array has millions of entries, the performance impact is negligible.
2

The problem is that Array.Sort<T>(T[], IComparer<T>) is not using a stable sort.

This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.

You'll have to sort your array using some other method.

2 Comments

Thanks, I did not know that stable sort was the type of sort I was looking for. This should help me in my search.
stable isn't a type of sort, its kindof a property of any/all sorting algorithms. either the algorithm is stable or it isn't. many sacrifice stability for performance, thinking that if the items are equal, their order isn't important.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.