简体   繁体   中英

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

I have values in a string list like

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

And I wanted to sort this by ascending order and the suffixes in descending order like below

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_

How can I code it in C#.net?

It is quite strange sorting, but if you really need it, try something like this:

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();

It looks like you have an error in your expected results, since AB1002_2 is in the input but not in the expected results.

Assuming that's just an error, and further assuming that the suffixes are limited to a single character or digit, you can solve the sorting by writing a special comparer like so:

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

Which you can then use to sort a string list, array or IEnumerable<string> , like so:

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

Finally I got the soln by this

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

and then PadNumbers function as like below

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM