【问题标题】:Sorting an array of enumeration对枚举数组进行排序
【发布时间】:2019-08-06 02:08:19
【问题描述】:

您好,我有一个枚举数组,我正在尝试按其枚举值对该数组进行排序并获取顶部的数组索引

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;

现在基本上,有了上面的内容,我需要按枚举值对设置数组进行排序,并获取顶部(比如说 3)项的数组索引;

所以我会返回值 1、2、8

我使用的平台不支持 LINQ,所以这些方便的功能不可用。

我一直在努力解决这个问题,但如果有另一双眼睛会有所帮助。

谢谢。

【问题讨论】:

  • 对不起,是的,编辑切断了部分开场描述。那应该是前 3 名。我正在尝试从该数组中获取前 3 个最高值。其中 - 在特定示例中 - 将是数组索引 1、2 和 8。
  • 您想要最高值还是这些值的索引?您可以创建一个列表或数组来保存结果,然后使用 for 或 foreach 循环遍历列表并收集结果。可能是您的讲师希望您先创建一个排序算法,然后收集结果(您是否正在学习冒泡排序?)。
  • 你使用什么框架?如果不是 LINQ,你可以使用什么
  • 那不是有效的代码...应该是Settings[0] = Values.LOW;
  • 您的意图并不清楚。对数组进行排序并获取前 3 个。如果对该数组进行排序,前三个将是相同的值。如果您尝试遍历数组并获得前 3 个最高值,它们也将相同。如果您想要前 3 个不同的最高值,那么这也是一个不同的操作。你的意图是排序,意图获得最高的最高,最高的不同,以上所有?

标签: c#


【解决方案1】:

实现一个包装器引用类型,

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
    }
}

用法-

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 将按照您的指定排序,保留它们在原始数组中的索引。

【讨论】:

  • 将索引和值存储在新类型中并对该类型进行比较是有意义的,但是CompareTo 内部的否定不在正确的位置。向前或向后迭代是调用者的工作。否定只有在比较器(即DescendingValueWrapperComparer : IComparer&lt;ValueWrapper&gt;)做出时才有意义。
【解决方案2】:

这个怎么样:

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;
    }

}

【讨论】:

    【解决方案3】:

    所以,既然你说你在 Linq 不可用的环境中工作,我假设泛型、可空对象等其他东西也将不可用。技术含量极低的解决方案。

    基本思路:

    对于每个可能的枚举值,从最高到最低,遍历列表。如果我们找到那个值,输出它并记住我们有多少输出。如果达到 3,则停止算法。

    所以,我们首先在列表中查找 HIGH,然后查找 MEDIUM,依此类推。

    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();
        }
    }
    

    按要求输出 1,2,8

    【讨论】:

    • @Efraim Newman 的方法在某些情况下可能会有更好的性能
    【解决方案4】:

    我不确定这是否正是您想要的,因为它不会对原始数组进行排序,但获取前三个值的索引的一种方法是将前三个值的索引简单地存储在另一个数组中.然后我们可以遍历原始数组,对于每个项目,看看它是否比我们迄今为止存储的索引处的任何项目都大。如果是,则将其与该项目交换。

    例如:

    // 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 }
    

    【讨论】:

      猜你喜欢
      • 2011-01-09
      • 1970-01-01
      • 2019-04-10
      • 1970-01-01
      • 2012-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多