Canuck Play
Canuck Play

Reputation: 49

Sorting an array of enumeration

Hello I have an array of enumerations, and I'm trying sort that array by their enumeration value and get the array index's of the top

private enum Values
{
LOW,
MEDIUM,
HIGH
}

private Values[] Settings = new Values[10];
Settings[0] = LOW;
Settings[1] = HIGH;
Settings[2] = MEDIUM;
Settings[3] = LOW;
Settings[4] = LOW;
Settings[5] = LOW;
Settings[6] = LOW;
Settings[7] = LOW;
Settings[8] = MEDIUM;
Settings[9] = MEDIUM;

Basically now, with what I have above, I need to sort the settings array by enumeration value and get the array indexes of the top (let's say 3) items;

So I'd get back values 1, 2, 8

The platform I'm using does not support LINQ so those handy functions are not available.

I've been trying to wrap my head around this but it would help to have another pair of eyes.

thanks.

Upvotes: 2

Views: 331

Answers (4)

Rufus L
Rufus L

Reputation: 37020

I'm not sure if this is exactly what you want because it doesn't sort the original array, but one way to get the indexes of the top three values is to simply store the indexes of the top values in another array. Then we can loop through the original array, and for each item, see if it's larger than any of the items at the indexes we've stored so far. If it is, then swap it with that item.

For example:

// Start the topIndexes array with all invalid indexes
var topIndexes = new[] {-1, -1, -1};

for (var settingIndex = 0; settingIndex < Settings.Length; settingIndex++)
{
    var setting = Settings[settingIndex];
    var topIndexLessThanSetting = -1;

    // Find the smallest topIndex setting that's less than this setting
    for (int topIndex = 0; topIndex < topIndexes.Length; topIndex++)
    {
        if (topIndexes[topIndex] == -1)
        {
            topIndexLessThanSetting = topIndex;
            break;
        }

        if (setting <= Settings[topIndexes[topIndex]]) continue;

        if (topIndexLessThanSetting == -1 ||
            Settings[topIndexes[topIndex]] < Settings[topIndexes[topIndexLessThanSetting]])
        {
            topIndexLessThanSetting = topIndex;
        }
    }

    topIndexes[topIndexLessThanSetting] = settingIndex;
}

// topIndexes = { 1, 2, 8 }

Upvotes: 0

NineBerry
NineBerry

Reputation: 28499

So, since you say you work in an environment where Linq is not available, I assume that other things like generics, nullables and so on will not be available either. A very low-tech solution.

Basic idea:

For every possible enum value, from highest to lowest, go through the list. If we find that value, output it and remember how many we have output. If we reach 3, stop the algorithm.

So, we first look for HIGH in the list, then for MEDIUM and so on.

class Program
{

    private enum Values
    {
        LOW,
        MEDIUM,
        HIGH
    }


    static void Main(string[] args)
    {
        // Sample data
        Values[] settings = new Values[10];
        settings[0] = Values.LOW;
        settings[1] = Values.HIGH;
        settings[2] = Values.MEDIUM;
        settings[3] = Values.LOW;
        settings[4] = Values.LOW;
        settings[5] = Values.LOW;
        settings[6] = Values.LOW;
        settings[7] = Values.LOW;
        settings[8] = Values.MEDIUM;
        settings[9] = Values.MEDIUM;


        // Get Values of the enum type
        // This list is sorted ascending by value but may contain duplicates
        Array enumValues = Enum.GetValues(typeof(Values));

        // Number of results found so far
        int numberFound = 0;

        // The enum value we used during the last outer loop, so
        // we skip duplicate enum values
        int lastValue = -1;

        // For each enum value starting with the highest to the lowest
        for (int i= enumValues.Length -1; i >= 0; i--)
        {
            // Get this enum value
            int enumValue = (int)enumValues.GetValue(i);

            // Check whether we had the same value in the previous loop
            // If yes, skip it.
            if(enumValue == lastValue)
            {
                continue;
            }
            lastValue = enumValue;

            // For each entry in the list where we are searching
            for(int j=0; j< settings.Length; j++)
            {
                // Check to see whether it is the currently searched value
                if (enumValue == (int)settings[j])
                {
                    // if yes, then output it.
                    Console.WriteLine(j);
                    numberFound++;

                    // Stop after 3 found entries
                    if (numberFound == 3)
                    {
                        goto finished;
                    }
                }
            }
        }

        finished: 

        Console.ReadLine();
    }
}

Output is as requested 1,2,8

Upvotes: 0

Efraim Newman
Efraim Newman

Reputation: 1031

how about this:

Values first = Values.Low,second = Values.Low,third = Values.Low;
int firstI = -1,secondI = -1, thirdI = -1;
for(int i = 0;i < Settings.Length;i++)
{
    if(Settings[i] > first || firstI == -1)
    {
        third = second;
        thirdI = secondI;

        second= first;
        secondI= firstI;

        first = Settings[i];
        firstI = i;
    } 
    else if(Settings[i] > second || secondI == -1)
    {
        third = second;
        thirdI = secondI;

        second = Settings[i];
        secondI = i;
    } 
    else if(Settings[i] > third || thirdI == -1)
    {
        third = Settings[i];
        thirdI = i;
    }

}

Upvotes: 1

jdphenix
jdphenix

Reputation: 15415

Implement a wrapper reference type,

class ValueWrapper : IComparable<ValueWrapper>
{
    public Values Value { get; set; }
    public int Index { get; set; }

    public int CompareTo(ValueWrapper other)
    {
        return this.Value.CompareTo(other.Value) * -1; // Negating since you want reversed order
    }
}

Usage -

ValueWrapper[] WrappedSettings = new ValueWrapper[10];
for(int i = 0; i < WrappedSettings.Length; i++)
{
    WrappedSettings[i] = new ValueWrapper { Value = Settings[i], Index = i };
}
Array.Sort(WrappedSettings);

WrappedSettings will be sorted as you specified, preserving the indexes they were in the original array.

Upvotes: 3

Related Questions