【问题标题】:How to Sort Integer Strings?如何对整数字符串进行排序?
【发布时间】:2010-10-21 13:58:04
【问题描述】:

在对具有整数值的字符串列表进行排序时,我遇到了一个奇怪的问题。但是,某些值可以以某些字符为前缀。

例如

// B1, 5, 50, A10, 7, 72, B3, A1, A2

基本上都有页码,应该这样排序:

// A1, A2, A10, B1, B3, 5, 7, 50, 72

但是如果我使用默认字符串排序,那么这些将被排序为

// A1, A10, A2, B1, B3, 5, 50, 7, 72

在 C# 中有任何解决方案吗?

【问题讨论】:

标签: c# .net sorting


【解决方案1】:

您正在寻找 Alphanum algorithm。对您来说幸运的是,已经存在许多实现。请参阅 here

【讨论】:

  • Alphanum 将返回 // 5, 7, 50, 72, A1, A2, A10, B1, B3 而不是 // A1 ... 5
  • 如果您浏览了一些代码示例,它会概述如何更改它以适应微妙的不同场景。
【解决方案2】:

这就是我为我们的应用程序解决它的方法,顺序就像在 windows 目录中一样:

public class NaturalSortComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        return StrCmpLogicalW(x, y);
    }

    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    public static extern int StrCmpLogicalW(string x, string y);
}

用法:

  NaturalSortComparer comparer = new NaturalSortComparer();
  return comparer.Compare(string1, string2);

但这可能不是你想要的:

// A1, A2, A10, B1, B3, 5, 7, 50, 72

这会给

// 5, 7, 50, 72, A1, A2, A10, B1, B3

【讨论】:

    【解决方案3】:

    您正在寻找的是自然排序。

    Jeff Atwood 曾经在他的博客上发表了一篇很棒的文章,解释了这个概念,并使用您可以作为示例的算法链接到各种其他来源。

    Sorting for Humans : Natural Sort Order

    【讨论】:

      【解决方案4】:

      这是一个自定义比较器,可以按照您需要的顺序进行排序。 请注意,此代码中没有错误/完整性检查:它假定所有字符串的格式都正确。

      public class MyComparer : IComparer<string>
      {
          public int Compare(string x, string y)
          {
              Match xMatch = Regex.Match(x, @"^(\D*)(\d+)$");
              Match yMatch = Regex.Match(y, @"^(\D*)(\d+)$");
      
              string xChars = xMatch.Groups[1].Value;
              string yChars = yMatch.Groups[1].Value;
      
              if ((xChars.Length == 0) && (yChars.Length > 0))
              {
                  return 1;
              }
              else if ((xChars.Length > 0) && (yChars.Length == 0))
              {
                  return -1;
              }
              else
              {
                  int charsResult = xChars.CompareTo(yChars);
      
                  return (charsResult != 0)
                      ? charsResult
                      : int.Parse(xMatch.Groups[2].Value)
                          .CompareTo(int.Parse(yMatch.Groups[2].Value));
              }
          }
      }
      

      你可以这样使用它:

      List<string> testList =
          new List<string>() { "B1","5","50","A10","7","72","B3","A1","A2" };
      
      testList.Sort(new MyComparer());    // A1, A2, A10, B1, B3, 5, 7, 50, 72
      

      【讨论】:

        【解决方案5】:

        好吧,您总是可以调用 Win32 API 函数StrCmpLogicalW,它完全符合您的要求(这是资源管理器用来对文件名进行排序的方法)。唯一可能的缺点是排序不区分大小写。

        【讨论】:

          【解决方案6】:

          不确定性能,确定可以优化,但它可以工作:

          string[] sort(string[] data)
          {
              return data
                  .OrderBy(s => Regex.Match(s, @"^\D").Length == 0)
                  .ThenBy(s => Regex.Match(s, @"\D*").Value)
                 .ThenBy(s => Int32.Parse(Regex.Match(s, @"\d+").Value)).ToArray();
          }
          
          var result = sort(new string[] { "B1", "5", "50", "A10", "7", "72", "B3", "A1", "A2" });
          

          【讨论】:

            猜你喜欢
            • 2023-03-22
            • 2017-09-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-04-21
            • 1970-01-01
            • 1970-01-01
            • 2021-12-26
            相关资源
            最近更新 更多