按数字位数的总和排序

时间:2015-10-28 10:16:23

标签: c# algorithm sorting

示例:

a =" 56 65 74 100 99 68 86 180 90",按数字排序变为:" 100 180 90 56 65 74 68 86 99"

当两个数字具有相同的"权重"时,让我们将它们分类为字符串而不是数字:100在180之前,因为它的重量是#34; (1)小于180(9)之一,180之前是90,因为,具有相同的"权重" (9)它以字符串形式出现。

列表中的所有数字都是正数,列表可以为空。

我的测试:

[TestMethod]
public void Test1()
{
     Assert.AreEqual("2000 103 123 4444 99", WeightSort.orderWeight("103 123 4444 99 2000"));
}

[TestMethod]
public void Test2()
{
    Assert.AreEqual("11 11 2000 10003 22 123 1234000 44444444 9999", WeightSort.orderWeight("2000 10003 1234000 44444444 9999 11 11 22 123"));
}

我的班级来计算权重的顺序:

public class WeightSort
{
    public static string orderWeight(string strng)
    {
        List<int> list = strng.Split(' ').Select(Int32.Parse).OrderBy(i => i).ToList();
        List<int> SumofNums = new List<int>();
        List<string> SumandNums = new List<string>();
        List<string> SumandNums2 = new List<string>();
        List<string> Nums = new List<string>();

        foreach (var itm in list)
        {
            int num = (int)GetSumOfDigits(itm);
            SumofNums.Add(num);
            SumandNums.Add(itm + "," + num);
        }
        SumofNums = SumofNums.OrderBy(i => i).ToList();
        string txt = "";            
        foreach (var itm in SumofNums)
        {
            var item = itm.ToString();
            if (!Nums.Contains(item))
            {
                foreach (var itm2 in SumandNums)
                {
                    var itm3 = itm2.Split(',');
                    if (item == itm3[1])
                    {
                        SumandNums2.Add(itm2);
                        if (string.IsNullOrEmpty(txt))
                            txt = itm3[0];
                        else
                            txt = txt + " " + itm3[0];
                    }
                }
                Nums.Add(item);
            }            
        }

        return txt;
    }

    static long GetSumOfDigits(long n)
    {
        long num2 = 0;
        long num3 = n;
        long r = 0;
        while (num3 != 0)
        {
            r = num3 % 10;
            num3 = num3 / 10;
            num2 = num2 + r;
        }

        return num2;
    }
}

如果只有一个但不重复,我可以处理。 请帮我改写我的课程,这样它也可以处理重复的内容。

数字之和:

string weights = "103 123 4444 99 2000";

1) 2000, digit sum = 2;
2) 103, digit sum = 4;
3) 123, digit sum = 6;
4) 4444, digit sum = 16;
5) 99, digit sum = 18;

the correct order is "2000 103 123 4444 99"

4 个答案:

答案 0 :(得分:5)

如果按重量排序,则可以使用 Linq

  • by 数字之和
  • 词典(“作为字符串”)

实施

  String a = "56 65 74 100 99 68 86 180 90";

  // 100 180 90 56 65 74 68 86 99
  String result = String.Join(" ", a
    .Split(' ')
    .OrderBy(item => item.Sum(ch => ch - '0')) // sum of digits
    .ThenBy(item => item));                    // lexicographic ("as string")

答案 1 :(得分:2)

试试这个:

var input = "103 123 4444 99 2000";
var sorted = input.Split(' ').OrderBy(s => s.Sum(c => c - '0')).ThenBy(s => s);
var result = string.Join(" ", sorted);

另外:我现在意识到,在我发布我的答案之前,Dmitry的答案已经演变成与我的相同。

新增内容:如果您发现s.Sum(c => c - '0')就像黑客一样,您可以using System.Globalization;代替s.Sum((Func<char, int>)CharUnicodeInfo.GetDecimalDigitValue)

您可以在lambda中进行验证。例如:

var sorted = input.Split(' ')
  .OrderBy(s => s.Sum(c => { if (c < '0' || c > '9') { throw new ArgumentOutOfRangeException("c", "Unexpected character."); } return c - '0'; }))
  .ThenBy(s => s);

答案 2 :(得分:0)

您也可以通过创建一个比较器来完成此操作,该比较器会告诉您某个值是否大于或小于另一个值然后可以使用。代码在很大程度上说明了一切:

void Main()
{
    var strings = new List<string>("2000 10003 1234000 44444444 9999 11 11 22 123".Split(' '));
    strings.Sort(new MyComparer());
    Console.WriteLine(String.Join(" ", strings));
}

public class MyComparer : IComparer<string>
{
    public int Compare(string a, string b)
    {
        var aWeight = GetWeight(a);
        var bWeight = GetWeight(b);
        if (aWeight==bWeight)
        {
            return String.Compare(a,b);
        }
        else
        {
            return aWeight < bWeight ? -1 : 1;
        }

    }

    private int GetWeight(string number)
    {
        var weight = 0;
        foreach(var digit in number)
        {
            weight+=Int32.Parse(digit.ToString());
        }
        return weight;
    }
}

关键是MyComparer类定义了一个带有两个值的公共方法。它获取对象的权重,如果它们相同则返回字符串比较。

然后可以将此比较器传递给List<T>之类的排序函数,然后进行排序。

这个更长,但我认为它值得分享,因为它更可重用(例如,如果你在代码中的很多地方都这样做,你可以将你的逻辑放在一个单独的类中),它有时可能是一个更具可读性。

我还注意到我不是ch - '0'的粉丝,因为它不是一目了然的,如果你不知道这个诀窍的话。同样在非数字字符的情况下,它仍然会做一些事情,但不一定是明智的。如果您传递任何非数字数据,我将抛出一个很好的老式异常。

答案 3 :(得分:-1)

我发现这个解决方案非常简短明了:

var orderedNumbers = "56 65 74 100 99 68 86 180 90".Split(' ')
    .OrderBy(GetWeight)
    .ThenBy(x => x);
var result = String.Join(" ", orderedNumbers);

这将首先计算任何给定数字的权重并按此值排序。如果它相等,则ThenBy - 子句进入游戏并通过执行字符串比较进一步对结果进行排序(因为第一个OrderBy返回的值是字符串列表)。

int GetWeight(string number)
{
    return number.Sum(x => CharUnicodeInfo.GetDecimalDigitValue(x));
}