C# 排序字符串数字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9988937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:01:14  来源:igfitidea点击:

sort string-numbers

c#stringlistsorting

提问by Karl

Possible Duplicate:
Natural Sort Order in C#

可能的重复:
C# 中的自然排序顺序

I have a list with a lot of numbers in it. But they are saved as strings because of some additional letters.

我有一个列表,里面有很多数字。但是由于一些额外的字母,它们被保存为字符串。

My list looks something like this:

我的列表看起来像这样:

1
10
11
11a
11b
12
2
20
21a
21c
A1
A2
...

but it should look like this

但它应该是这样的

1
2
10
11a
11b
...
A1
A2
...

How do i sort my list to get this result?

如何对我的列表进行排序以获得此结果?

采纳答案by Richard

Going by the previous comments, I would also implement a custom IComparer<T>class. From what I can gather, the structure of the items is either a number, of a combination of a number followed by a letter(s). If this is the case, the following IComparer<T>implementation should work.

根据之前的评论,我还将实现一个自定义IComparer<T>类。据我所知,项目的结构要么是一个数字,要么是一个数字后跟一个字母的组合。如果是这种情况,下面的IComparer<T>实现应该可以工作。

public class CustomComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        var regex = new Regex("^(d+)");

        // run the regex on both strings
        var xRegexResult = regex.Match(x);
        var yRegexResult = regex.Match(y);

        // check if they are both numbers
        if (xRegexResult.Success && yRegexResult.Success)
        {
            return int.Parse(xRegexResult.Groups[1].Value).CompareTo(int.Parse(yRegexResult.Groups[1].Value));
        }

        // otherwise return as string comparison
        return x.CompareTo(y);
    }
}

With this IComparer<T>, you'll be able to sort your list of stringby doing

有了这个IComparer<T>,您将能够string通过执行以下操作来对您的列表进行排序

var myComparer = new CustomComparer();
myListOfStrings.Sort(myComparer);

This has been tested with the following items:

这已经通过以下项目进行了测试:

2, 1, 4d, 4e, 4c, 4a, 4b, A1, 20, B2, A2, a3, 5, 6, 4f, 1a

2, 1, 4d, 4e, 4c, 4a, 4b, A1, 20, B2, A2, a3, 5, 6, 4f, 1a

and gives the result:

并给出结果:

1, 1a, 2, 20, 4a, 4b, 4c, 4d, 4e, 4f, 5, 6, A1, A2, a3, B2

1, 1a, 2, 20, 4a, 4b, 4c, 4d, 4e, 4f, 5, 6, A1, A2, a3, B2

回答by zmbq

Well, you need to extract the number from each string and then sort the list of strings based on the list of numbers as keys. Do this in two steps.

那么,您需要从每个字符串中提取数字,然后根据作为键的数字列表对字符串列表进行排序。分两步执行此操作。

To extract the number from each string, the simplest way I think is to use a regular expression - look for a match for (\d+)(if you have negative or decimal numbers, you'll have to use a different regular expression). Let's say you did that in a function called ExtractNumber

要从每个字符串中提取数字,我认为最简单的方法是使用正则表达式 - 寻找匹配项(\d+)(如果您有负数或十进制数,则必须使用不同的正则表达式)。假设您在一个名为ExtractNumber

Now you can use some creative LINQ to sort, like this:

现在可以使用一些有创意的 LINQ 进行排序,如下所示:

strings.Select(s=>new { key=ExtractNumber(s), value=s }) // Create a key-value pair
       .OrderBy(p=>p.key)                                // Sort by key
       .Select(p=>p.Value);                              // Extract the values

回答by Alexis

I'm rather new to C#, but here is a solution I appreciate in Java: you need to proceed in 2 steps, first define a customized IComparer and second use it in when calling the sort method. So you should be able to do something like:

我对 C# 比较陌生,但这是我在 Java 中欣赏的解决方案:您需要分两步进行,首先定义一个自定义的 IComparer,然后在调用 sort 方法时使用它。因此,您应该能够执行以下操作:

public class MyListSorter : IComparer<MyObject>
{
  public int Compare(MyObject obj1, MyObject obj2)
  {
    if ( !Char.IsNumber(obj1) && Char.IsNumber(obj2) )
    {
       return 0;
    }
    else if ( Char.IsNumber(obj1) && !Char.IsNumber(obj2) )
    {
      return 1;
    }
    else
    {
      return obj2.CompareTo(obj1);
    }
  }
}

and then

进而

myObjectList.Sort(new MyListSorter());

More infos on IComparer: http://support.microsoft.com/kb/320727

有关 IComparer 的更多信息:http: //support.microsoft.com/kb/320727

回答by L.B

Since this includes many string operations, regex etc., I don't think it is an efficient algorithm but It seems to work.

由于这包括许多字符串操作、正则表达式等,我认为它不是一种有效的算法,但它似乎有效。

List<string> list1 = new List<string>() { "11c22", "1", "10", "11", "11a", "11b", "12", "2", "20", "21a", "21c", "A1", "A2" };
List<string> list2 = new List<string>() { "File (5).txt", "File (1).txt", "File (10).txt", "File (100).txt", "File (2).txt" };
var sortedList1 = NaturalSort(list1).ToArray();
var sortedList2 = NaturalSort(list2).ToArray();


public static IEnumerable<string> NaturalSort(IEnumerable<string> list)
{
    int maxLen = list.Select(s => s.Length).Max();
    Func<string, char> PaddingChar = s => char.IsDigit(s[0]) ? ' ' : char.MaxValue;

    return list
            .Select(s =>
                new
                {
                    OrgStr = s,
                    SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, PaddingChar(m.Value)))
                })
            .OrderBy(x => x.SortStr)
            .Select(x => x.OrgStr);
}