Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按数字的位数和排序_C#_Algorithm_Sorting - Fatal编程技术网

C# 按数字的位数和排序

C# 按数字的位数和排序,c#,algorithm,sorting,C#,Algorithm,Sorting,例如: 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.Ar

例如:

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;
    }
}
如果按权重方式排序,则可以使用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")
如果按权重方式排序,则可以使用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 orderedNumbers = "56 65 74 100 99 68 86 180 90".Split(' ')
    .OrderBy(GetWeight)
    .ThenBy(x => x);
var result = String.Join(" ", orderedNumbers);
这将首先计算任何给定数字的权重,并按此值排序。如果相等,ThenBy子句将进入播放,并通过执行字符串比较对结果进行进一步排序,因为第一个OrderBy返回的值是字符串列表


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

var orderedNumbers = "56 65 74 100 99 68 86 180 90".Split(' ')
    .OrderBy(GetWeight)
    .ThenBy(x => x);
var result = String.Join(" ", orderedNumbers);
这将首先计算任何给定数字的权重,并按此值排序。如果相等,ThenBy子句将进入播放,并通过执行字符串比较对结果进行进一步排序,因为第一个OrderBy返回的值是字符串列表

试试这个:

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.Sumc=>c-'0'像一个黑客,那么您可以使用System.Globalization;改为使用s.sumfuncharlunicodeinfo.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);
试试这个:

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.Sumc=>c-'0'像一个黑客,那么您可以使用System.Globalization;改为使用s.sumfuncharlunicodeinfo.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的排序函数,然后进行排序

这要长得多,但我认为它值得分享,因为它更具可重用性。例如,如果你在代码中的很多地方这样做,你可以在一个类中拥有你的逻辑,有时它的可读性会更好


我还注意到,我不喜欢使用ch-“0”作为获取字符int值的一种方法,因为如果你不知道诀窍,它的作用并不总是一目了然。此外,在非数字字符的情况下,它仍然会做一些事情,只是不一定是明智的事情。我的将抛出一个好的老式异常,如果您传递任何非数字数据,它就会被捕获。

您也可以通过创建一个比较器来实现这一点,该比较器告诉您一个值是否大于或小于另一个值,然后可以使用它。该准则在很大程度上说明了这一点:

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的排序函数,然后进行排序

这要长得多,但我认为它值得分享,因为它更具可重用性。例如,如果你在代码中的很多地方这样做,你可以在一个类中拥有你的逻辑,有时它的可读性会更好


我还注意到,我不喜欢使用ch-“0”作为获取字符int值的一种方法,因为如果你不知道诀窍,它的作用并不总是一目了然。此外,在非数字字符的情况下,它仍然会做一些事情,只是不一定是明智的事情。我的方法只是抛出一个很好的老式异常,如果你传递任何非数字数据,它就会被捕获。

你从哪里获得权重?为了简化事情,我建议你编写一个方法GetWeitgth,将给定数字的权重计算为其cifer的总和。然后是一个简单的OrderBy语句看看它们告诉你所有你需要知道的测试..你的代码很好地处理重复。你能解释一下你对重复项的期望吗?我已经添加了一点更多的信息。试着读一下。你从哪里得到权重?为了简化事情,我建议你写一个方法GetWeitgth,它将给定数字的权重计算为其CIFER之和。那么这是一个简单的命令

通过语句查看测试,它们告诉您所有您需要知道的内容。您的代码可以很好地处理重复项。你能解释一下你对复制品的期望吗?我已经补充了一些信息,试着读一下。。数字的总和在哪里?@ArchAngel:如果a=103 123 4444 99 2000,我的实现的输出是2000 103 123 4444 99。你已经得到了最好的和可以理解的解决方案。数字的总和在哪里?@ArchAngel:如果a=103 123 4444 99 2000我的实现的输出是2000 103 123 4444 99您已经得到了最好的、可以理解的解决方案。您可以使用CharUnicodeInfo.GetDecimalDigitValuex,而不是Convert.ToInt32Char.GetNumericValuex。GetDecimalDigitValuex只需要使用System.Globalization;。实际上它变成了返回号。SumCharUnicodeInfo.GetDecimalDigitValue。@JeppeStigNielsen你说得对,我更新了我的答案,而不是Convert.ToInt32Char.GetNumericValuex你可以使用CharUnicodeInfo.GetDecimalDigitValuex只需要使用System.Globalization;。实际上它变成了返回号。SumCharUnicodeInfo.GetDecimalDigitValue。@JeppeStigNielsen你说得对,我已经更新了我的answer@ArchAngel为什么?然而,这不是克里斯的错误,因为你以前没有提到过。因为要写的代码太多了,我的答案必须简短。@ArchAngel:没关系。我很欣赏它的冗长,但这有时也有好处。正如HimBromBeere提到的,您没有指定简明,因此我认为它为现有答案添加了一个很好的替代方案。不过,我很高兴你不用它,只要我没有得到任何反对票,而且我知道你没有,别担心@大天使为什么?然而,这不是克里斯的错误,因为你以前没有提到过。因为要写的代码太多了,我的答案必须简短。@ArchAngel:没关系。我很欣赏它的冗长,但这有时也有好处。正如HimBromBeere提到的,您没有指定简明,因此我认为它为现有答案添加了一个很好的替代方案。不过,我很高兴你不用它,只要我没有得到任何反对票,而且我知道你没有,别担心对于这种情况,我不喜欢c-'0'和CharUnicodeInfo.GetDecimalDigitValue的原因是,即使传入的字符是字母或其他任何内容,它们都将返回int值。这可能是因为数据已经过彻底验证,但每当我编写的代码没有抛出无效输入时,我都会感到很难过@Chris您可以检查lambda中的无效字符,请参见上面的编辑。当然,这可能会导致希望使用命名的常用用户定义方法,而不是lambda.Yup。这就是为什么我选择了完全成熟的比较器的部分原因,因为在一个lambda中要做的事情有点多。在这种情况下,我不喜欢c-'0'和CharUnicodeInfo.GetDecimalDigitValue的原因是,即使传入的字符是字母或其他任何东西,两者都将返回int值。这可能是因为数据已经过彻底验证,但每当我编写的代码没有抛出无效输入时,我都会感到很难过@Chris您可以检查lambda中的无效字符,请参见上面的编辑。当然,这可能会导致希望使用命名的常用用户定义方法,而不是lambda.Yup。这就是为什么我选择完整的比较器的部分原因,因为在一个lambda中,它感觉有点太多了。