如何排序整数字符串?

时间:2009-04-24 10:23:24

标签: c# .net sorting

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

e.g。

// 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#中的任何解决方案?

6 个答案:

答案 0 :(得分:17)

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

答案 1 :(得分:5)

这就是我为我们的应用程序解决它的方式,顺序就像在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

答案 2 :(得分:3)

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

杰夫阿特伍德曾在他的博客上发表了一篇很棒的文章,解释了这个概念,并以你可以采用的算法链接到其他各种来源。

Sorting for Humans : Natural Sort Order

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

好吧,你总是可以调用Win32 API函数StrCmpLogicalW,它完全符合你的需要(它是Explorer用来排序文件名的东西)。唯一可能的缺点是排序不区分大小写。

答案 5 :(得分:0)

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

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