【问题标题】:Sorting 50+-digit numbers in array [closed]对数组中的 50+ 位数字进行排序 [关闭]
【发布时间】:2017-02-21 21:54:05
【问题描述】:

我有一个包含 50+ 位数字的字符串数组。我需要将它们转换为现实世界的整数并按升序排列它们。当我的数字具有不同大小的位数时,它可以工作,但在这种情况下,如果所有数字都具有相同大小的位数,它将不起作用:

string[] unsorted = {"324141241413213123123123132131451231231321363435243321413153412465745238454211425241244252423234234", "324141241413213123123123132131451231231321363435243321413153412465745238454211425241244252423234235"
        ,"324141241413213123123123132131451231231321363435243321413153412465745238454211425241244252423234200","324141241413213123123123132131451231231321363435243321413153412465745238454211425241244252423234100","324141241413213123123123132131451231231321363435243321413153412465745238454211425241244252423234731"};
var sorted = unsorted.OrderBy(s => double.Parse(s));

什么是最好的解决方案?

【问题讨论】:

  • 什么测试用例没有通过?
  • 什么样的数字,可以解析成BigInteger的东西?
  • 如果您遇到数据类型问题(就数字容量而言),您可以用前导零填充字符串并按字母顺序排序。
  • 太短,没有足够的细节。提供示例数据并发布预期结果与实际结果。
  • @barakmanos:如果您想了解规范的内容,它以多种格式发布在互联网上。规范说 C# 字符串是 UTF-16 编码的。

标签: c# algorithm linq sorting


【解决方案1】:

如果您使用的是 整数,您可以将它们解析为 BigIntegerdoubledecumal 对于此类数字来说太短,例如 @987654325 @ 仅 29 位数字):

using System.Numerics;

...

string[] data = ...

var ordered = data
  .OrderBy(item => BigInteger.Parse(item))
  .ToArray(); // if you want materialization to array

如果您使用的是非负整数,您可以按长度对它们进行排序,然后按字典顺序(无需转换):

string[] data = ...

var ordered = data
  .OrderBy(item => item.Length)
  .ThenBy(item => item)
  .ToArray(); // if you want materialization to array

任何整数的相同方法(参见 Jason P Sallinger 的评论)也是可能的,但不是那么优雅:

  var ordered = data
    .Where(item => item.StartsWith("-"))
    .OrderByDescending(item => item.Length)
    .ThenByDescending(item => item)
    .Concat(data
       .Where(item => !item.StartsWith("-"))
       .OrderBy(item => item.Length)
       .ThenBy(item => item))
    .ToArray();

最后,请看 Natural Sort Order in C#

【讨论】:

  • 如果确实有负整数,可以拆分集合,分两遍进行,然后合并两个数组
  • @Jason P Sallinger:谢谢,我明白了!但是这个想法的实现会很繁琐。
  • 真的。至少这将是朝着故障安全方向迈出的一步
  • @DmitryBychenko 我尝试了两种解决方案,并且都通过了所有测试用例。谢谢你:)
  • @gagro:不客气!
【解决方案2】:

假设它们被修剪(没有前导零)没有逗号的正整数:

unsorted.OrderBy(s => s.Length).ThenBy(s => s)

会起作用,因为比另一个未修剪数字长的未修剪整数将大于它。

也适用于否定:

unsorted.Order(s => s[0] != '-').ThenBy(s => s.Length).ThenBy(s => s)

由于布尔值在 true 之前排序为 false,并且您希望以 - 开头的字符串排在非布尔值之前。

如果事情比这更复杂,我会使用 IEqualityComparer<string>Compare 方法:

  1. 如果只有一个有-,那么它会排在第一位。
  2. 否则,如果他们都有-,则修剪掉-,使用结果调用自身,然后否定该结果。
  3. 修剪任何数千个分组(, 英文使用)。
  4. 获取每个小数点分隔符的长度(英文使用.),如果没有,则获取完整长度。如果不同,则最短的是最小的。
  5. 序号字符串比较。

【讨论】:

  • 问题是我使用了 double 而不是 BigInteger,因为 double 无法处理那些大数字。将 double 更改为 BigInteger 可解决此问题。
【解决方案3】:

试试这个; (linq 中的一个简单解决方案)它适用于正整数和负整数。

string[] array = { "2525213", "2525211", "-2525214" };

        var result = array.OrderBy(x => BigInteger.Parse(x));

        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }

【讨论】:

  • 嗯,这基本上是从@Dmitry 的答案中复制和粘贴的,这些不是 50 位以上的数字。
猜你喜欢
  • 2021-11-25
  • 1970-01-01
  • 2014-10-14
  • 2022-06-21
  • 1970-01-01
  • 2021-11-28
  • 2021-09-08
  • 2011-09-04
  • 1970-01-01
相关资源
最近更新 更多