如何在 C# .net 中对包含带有字母和数字的字符串的字符串列表进行降序排序?

How to sort descending a string list contains strings with alphabets & numbers in C# .net?

我在字符串列表中有值,例如

AB1001_A
AB1001_B
AB1002_2
AB1002_C
AB1003_0
AB1003_
AB1003_B
AB1003_A
AB1001_0
AB1001_1
AB1001_2
AB1001_C
AB1002_B
AB1002_A

我想按升序排序,后缀按降序排序,如下所示

AB1001_2
AB1001_1
AB1001_0
AB1001_C
AB1001_B
AB1001_A
AB1002_0
AB1002_B
AB1002_A
AB1003_0
AB1003_B
AB1003_A
AB1003_

如何在 C#.net 中编写代码?

您的预期结果似乎有误,因为 AB1002_2 在输入中但不在预期结果中。

假设这只是一个错误,并进一步假设后缀仅限于单个字符或数字,您可以通过编写一个特殊的比较器来解决排序问题:

static int compare(string x, string y)
{
    var xParts = x.Split('_', StringSplitOptions.RemoveEmptyEntries);
    var yParts = y.Split('_', StringSplitOptions.RemoveEmptyEntries);

    if (xParts.Length != yParts.Length)
        return yParts.Length - xParts.Length; // No suffix goes after suffix.

    if (xParts.Length == 0) // Should never happen.
        return 0;

    int comp = string.Compare(xParts[0], yParts[0], StringComparison.Ordinal);

    if (comp != 0 || xParts.Length == 1)
        return comp;

    if (char.IsDigit(xParts[1][0]) && !char.IsDigit(yParts[1][0]))
        return -1; // Digits go before non-digit.

    if (!char.IsDigit(xParts[1][0]) && char.IsDigit(yParts[1][0]))
        return 1; // Digits go before non-digit.

    return string.Compare(yParts[1], xParts[1], StringComparison.Ordinal);
}

然后您可以使用它来对字符串列表、数组或 IEnumerable<string> 进行排序,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            var strings = new []
            {
                "AB1001_A",
                "AB1001_B",
                "AB1002_2",
                "AB1002_C",
                "AB1003_0",
                "AB1003_",
                "AB1003_B",
                "AB1003_A",
                "AB1001_0",
                "AB1001_1",
                "AB1001_2",
                "AB1001_C",
                "AB1002_B",
                "AB1002_A",
            };

            static int compare(string x, string y)
            {
                var xParts = x.Split('_', StringSplitOptions.RemoveEmptyEntries);
                var yParts = y.Split('_', StringSplitOptions.RemoveEmptyEntries);

                if (xParts.Length != yParts.Length)
                    return yParts.Length - xParts.Length;

                if (xParts.Length == 0)
                    return 0;

                int comp = string.Compare(xParts[0], yParts[0], StringComparison.Ordinal);

                if (comp != 0 || xParts.Length == 1)
                    return comp;

                if (char.IsDigit(xParts[1][0]) && !char.IsDigit(yParts[1][0]))
                    return -1; // Digits go before non-digit.

                if (!char.IsDigit(xParts[1][0]) && char.IsDigit(yParts[1][0]))
                    return 1; // Digits go before non-digit.

                return string.Compare(yParts[1], xParts[1], StringComparison.Ordinal);
            }

            var stringList = strings.ToList();
            stringList.Sort(compare);

            Console.WriteLine("Sorted list:");
            Console.WriteLine(string.Join("\n", stringList));

            var stringArray = strings.ToArray();
            Array.Sort(stringArray, compare);

            Console.WriteLine("\nSorted array:");
            Console.WriteLine(string.Join("\n", stringArray));

            var sequence = strings.Select(element => element);
            var sortedSeq = sequence.OrderBy(element => element, Comparer<string>.Create(compare));

            Console.WriteLine("\nSorted sequence:");
            Console.WriteLine(string.Join("\n", sortedSeq));
        }
    }
}

Try it online on .Net Fiddle

这是一种很奇怪的排序,但如果你真的需要它,试试这样:

List<string> lItemsOfYourValues = new List<string>() {"AB1001_A","AB1001_B","AB1001_0" /*and next your values*/};

List<Tuple<string,string,string>> lItemsOfYourProcessedValues = new List<Tuple<string,string,string>>();
string[] arrSplitedValue;

for(int i = 0; i < lItemsOfYourValues.Count; i++) 
{

arrSplitedValue = lItemsOfYourValues[i].Split("_");

lItemsOfYourProcessedValues.add(new Tuple<string,string,string>(lItemsOfYourValues[i], arrSplitedValue[0], arrSplitedValue[1]));

}

List<string> lSortedValues = lItemsOfYourProcessedValues.OrderBy(o => o.Item2).ThenByDescending(o => o.Item3).Select(o => o.Item1).ToList();

最后我得到了解决方案

var mystrings = new []
            {
                "AB1001_A",
                "AB1001_B",
                "AB1002_2",
                "AB1002_C",
                "AB1003_0",
                "AB1003_",
                "AB1003_B",
                "AB1003_A",
                "AB1001_0",
                "AB1001_1",
                "AB1001_2",
                "AB1001_C",
                "AB1002_B",
                "AB1002_A",
            };


mystrings.Cast<string>().OrderBy(x => PadNumbers(x));

然后 PadNumbers 的功能如下

        public static string PadNumbers(string input)
        {
            return Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0'));
        }