将双精度列表转换为分组字符串

该程序的输入为双精度列表,输出为包含按值分组的列表值的字符串。如果列表值相等,则将它们分组。像这样的东西:输入9,77,5,5,31 =>输出9 77 2 * 5 31

为此,我在C#中创建了一个算法(在Java中,我认为几乎是相同的),但是我不确定它的速度或代码质量是否可以改进,或者是否存在一些我看不到的错误。下面还有另外一些输入,输出示例的算法。

          List<double> input = new List<double> { 11, 32, 32, 43}; // output 11 2*32 43
        //List<double> input = new List<double> { 11, 11, 43, 43 }; // output 2*11 2*43
        //List<double> input = new List<double> { 10, 11, 12, 13, 14, 15, 16 }; // output 10 11 12 13 14 15 16
        //List<double> input = new List<double> { 11, 11, 11, 11, 11 }; // output 5 * 11
        //List<double> input = new List<double> { 11, 11, 32, 22, 22, 22, 4, 10, 10 }; // output 2*11 32 3*22 4 2*10

        string listAsString = string.Empty;
        double nextElem = double.MinValue;
        for (int i = 0; i < input.Count; i++)
        {
            double currentElem = input[i];

            if (i + 1 < input.Count)
            {
                nextElem = input[i + 1];
            }

            int equalCount = 0;
            while (currentElem.Equals(nextElem) && i < input.Count)
            {
                equalCount++;
                i++;
                currentElem = nextElem;

                if (i < input.Count)
                {
                    nextElem = input[i];
                }
            }

            if (equalCount < 2)
            {
                listAsString += currentElem + " ";
            }
            else
            {
                listAsString += equalCount + "*" + currentElem + " ";
                i--;
            }
        }

        Console.WriteLine(listAsString);

如果您发现了一些错误或看到可以完成的改进,请告诉我。

另外,如果您知道此要求的另一种实现,请添加它,以便可以对算法之间的结果,速度,代码质量进行比较...并找到处理此问题的最佳方法。

伊万·斯托夫(Ivan Stoev)

由于要求仅对连续的相等值进行分组,因此另一个答案中提到Dictionary和LINQGroupBy方法不适用,因为它们将对诸如的输入序列产生不正确的结果1,2,1同样,没有标准的LINQ方法可以进行这种分组(最终Aggregate方法除外,但仅相当于效率低下的for/foreach循环等效方法)。

不久,您的算法最适合此类任务。但是执行不是。

主要的瓶颈是Peroxy提到的字符串连接,该字符串连接(在其他答案中也提到)可以通过使用StringBuilder该类轻松修复一旦执行此操作,性能将很好。

我在实现中看到的另一个问题是特殊值(double.MinValue)的使用,重复的拐角大小写检查,for主体内部递减的循环变量等。因此,尽管它可能起作用并且我没有直接看到错误,但是很难遵循只需阅读实现,即可发现算法逻辑并发现潜在的错误。该算法本身非常简单,我可以通过以下方式实现:

static string ListAsString(List<double> input)
{
    var sb = new StringBuilder();
    for (int i = 0; i < input.Count; )
    {
        var value = input[i];
        int count = 1;
        while (++i < input.Count && input[i] == value)
            count++;
        if (sb.Length > 0) sb.Append(' ');
        if (count > 1) sb.Append(count).Append('*');
        sb.Append(value);
    }
    return sb.ToString();
}

IMO非常容易遵循。请注意,没有重复的代码,没有特殊的值,并且循环变量的i前进仅在外部循环体内的一个位置进行。同样,这与性能无关(由StringBuilder使用情况提供),而仅仅是可读性,冗余消除和较少的错误倾向。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

TOP 榜单

热门标签

归档