如何找到列表<double>的模式?

Edw*_*rak 12 c#

我有一个清单:

List<double> final=new List<double>();
final.Add(1);
final.Add(2);
final.Add(3);
Run Code Online (Sandbox Code Playgroud)

我可以使用哪种方法来查找此列表的模式?此外,如果有两种模式,该函数将返回两者中较小的一种.

usr*_*usr 27

int? modeValue =
 final
 .GroupBy(x => x)
 .OrderByDescending(x => x.Count()).ThenBy(x => x.Key)
 .Select(x => (int?)x.Key)
 .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

所需要的只是一些组合的LINQ操作.您也可以使用查询表达式表达相同的内容.

如果列表为空,modeValue将是null.


nic*_*k_w 5

usr给出的答案似乎可以解决问题,但如果你想要一些非Linq,试试这个:

    public int? FindMode(List<int> sample)
    {
        if (sample == null || sample.Count == 0)
        {
            return null;
        }

        List<int> indices = new List<int>();
        sample.Sort();

        //Calculate the Discrete derivative of the sample and record the indices
        //where it is positive.
        for (int i = 0; i < sample.Count; i++)
        {
            int derivative;

            if (i == sample.Count - 1)
            {
                //This ensures that there is a positive derivative for the
                //last item in the sample. Without this, the mode could not
                //also be the largest value in the sample.
                derivative = int.MaxValue - sample[i];
            }
            else
            {
                derivative = sample[i + 1] - sample[i];
            }

            if (derivative > 0)
            {
                indices.Add(i + 1);
            }
        }

        int maxDerivative = 0, maxDerivativeIndex = -1;

        //Calculate the discrete derivative of the indices, recording its
        //maxima and index.
        for (int i = -1; i < indices.Count - 1; i++)
        {
            int derivative;

            if (i == -1)
            {
                derivative = indices[0];
            }
            else
            {
                derivative = indices[i + 1] - indices[i];
            }

            if (derivative > maxDerivative)
            {
                maxDerivative = derivative;
                maxDerivativeIndex = i + 1;
            }
        }

        //The mode is then the value of the sample indexed by the
        //index of the largest derivative.
        return sample[indices[maxDerivativeIndex] - 1];
    }
Run Code Online (Sandbox Code Playgroud)

我在这里所做的基本上是在维基百科页面的样本模式部分中描述的算法的实现.请注意,通过首先对样本进行排序,这将在多模式情况下返回较小的模式.

此外,维基百科页面上的Octave代码假定基于1的索引; 因为C#是基于0的,你会看到我使用indices.Add(i + 1)maxDerivativeIndex = i + 1补偿.出于同样的原因,我还习惯indices[maxDerivativeIndex] - 1在返回最终模式时映射回基于0的索引.


因为这种方法比使用Dictionary累积计数的直观方法稍微不那么明显,所以这是一个有效的例子.

调用上面的方法:

int? mode = FindMode(new List<int>(new int[] { 1, 3, 6, 6, 6, 6, 7, 7, 12, 12, 17 }));
Run Code Online (Sandbox Code Playgroud)

在初始检查和排序之后,离散导数(即indices列表)在第一个for循环的末尾看起来像这样:

[1, 2, 6, 8, 10, 11]
Run Code Online (Sandbox Code Playgroud)

接下来,我们计算出离散导indices.出于效率原因,我不是将它们存储在一个列表中(毕竟我们只想要它们中最大的一个),但它们可以解决:

[1, 1, 4, 2, 2, 1]
Run Code Online (Sandbox Code Playgroud)

因此,maxDerivative最终为4和maxDerivativeIndex2.因此:

sample[indices[maxDerivativeIndex] - 1]
    -> sample[indices[2] - 1]
    -> sample[6 - 1]
    -> 6
Run Code Online (Sandbox Code Playgroud)