S. Walker
S. Walker

Reputation: 2162

Quickly sort list of objects to match the order of an array which contains the value of a property

I have a method that accepts a string[]. It takes this array and sorts it based off a custom algebraic formula we have. This algebraic formula is quite complex and cannot (or should not) be adapted to accept anything other than an IEnumerable<string>.

I'm tasked with creating a wrapper function for this method that accepts an IEnumerable<T> where T implements an interface exposing the string to be used for sorting.

Based on this, I have created a method that iterates the genetic enumerable, extracts the string and passes the resulting array into our custom sort function. This works, but I end up with a sorted array of strings, completely disconnected from the original IEnumerable <T> . How can I sort the IEnumerable <T> to match the array of strings returned from our custom sort function?

For example.

private IEnumerable<T> Sort(IEnumerable<T> objects) where T: ICustomSortable
{
    string[] stringsToSort = new string[objects.Count()];
    for (int i = 0; i < stringsToSort.length; i++)
        stringsToSort[i] = objects.getString();

    stringsToSort = customSortFunction(stringsToSort);

    //somehow sort the objects so that they are in the same order as stringsToSort?
    /*
    The result is valid when:
     objects[0].getString() == stringsToSort[0]
     objects[1].getString() == stringsToSort[1]
     objects[2].getString() == stringsToSort[2]
      ...
     objects[n].getString() == stringsToSort[n]
    */
}

EDIT: The strings retrieved from the customSortFunction may not be unique. This means that two objects whose strings are the same, should both exist in the result. While the ordering of objects with the same string value is irrelevant, they should remain in place when referencing the result as a whole.

Upvotes: 1

Views: 145

Answers (1)

realharry
realharry

Reputation: 1575

What you need is a mapping from the object string value to the object itself. Something like

IDictionary<string, T>

Just create this mapping (before or after sorting), and after sorting is done based on their string values, create a new sorted list of T, by iterating through the (sorted) string list and using the mapping to get the corresponding T.

EDIT: Based on the comment that the string values may not be all distinct, all you need to do is to create a mapping from the string to a set/list of Ts. Something like,

IDictionary<string, IList<T>>

[A] While you are looping through IEnumerable<T>, (1) if you see a new (string) key, create a new list and add the owner T for the string, and (2) if you find a key that is already in the dictionary, retrieve the list, and append the new owner T into the list.

[B] After sorting is done, go through the sorted string/key list, and find the corresponding Ts (one or more), and create a new list of Ts by consecutively appending the Ts.

This is not the most elegant way (a better way is obviously to use some kind of comparators), but it's straightforward and will get the job done.

Upvotes: 2

Related Questions