繁体   English   中英

按数字的总和排序

[英]Order by sum of digits of number

例子:

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

当两个数字具有相同的“权重”时,让我们将它们归类为字符串而不是数字:100 在 180 之前,因为它的“权重”(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"

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

  • 数字总和
  • 按字典顺序(“作为字符串”)

实施

  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")

尝试这个:

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

补充:我现在意识到德米特里的答案在我发布我的之前已经演变成和我的一样。

新增:如果你发现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);

您也可以通过创建一个比较器来做到这一点,该比较器告诉您一个值是大于还是小于另一个值,然后可以使用。 代码在很大程度上不言自明:

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'作为获取字符 int 值的一种方式,因为如果您不知道诀窍,它的作用并不总是一目了然。 同样在非数字字符的情况下,它仍然会做一些事情,只是不一定是任何明智的事情。 我的只会抛出一个很好的老式异常,如果您向它传递任何非数字数据,则可以捕获该异常。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM