Почему Double.MIN_VALUE не отрицательный

Это называется «естественным порядком сортировки» и обычно используется для сортировки таких элементов, как те, которые у вас есть, например, имена файлов и т. д.

Вот наивный (в том смысле, что, вероятно, unicode-problems с ним), которая, похоже, делает трюк:

Вы можете скопировать код ниже в LINQPad , чтобы выполнить его и проверить.

В основном алгоритм сравнения будет идентифицировать числа внутри строк и обрабатывать их путем заполнения самого короткого с ведущими нулями, поэтому, например, две строки "Test123Abc" и "Test7X" следует сравнивать, как если бы они были "Test123Abc" и "Test007X" , который должен производить то, что вы хотите.

Однако, когда я сказал «наивно», я имею в виду, что у меня, вероятно, есть тонны реальных проблем с Юникодом, например, обработка диакритических знаков и символов с несколькими кодовыми точками.

Примечания:

  • Реализация фактически не анализирует числа, поэтому произвольно длинные числа должны работать просто отлично
  • Так как он фактически не анализирует числа как «числа», числа с плавающей точкой не будут обрабатываться должным образом, «123.45» против «123.789» будет сравниваться как «123.045» против «123.789», , что неверно.

Код:

void Main()
{
    List input = new List
    {
        "1", "5", "3", "6", "11", "9", "A1", "A0"
    };
    var output = input.NaturalSort();
    output.Dump();
}

public static class Extensions
{
    public static IEnumerable NaturalSort(
        this IEnumerable collection)
    {
        return NaturalSort(collection, CultureInfo.CurrentCulture);
    }

    public static IEnumerable NaturalSort(
        this IEnumerable collection, CultureInfo cultureInfo)
    {
        return collection.OrderBy(s => s, new NaturalComparer(cultureInfo));
    }

    private class NaturalComparer : IComparer
    {
        private readonly CultureInfo _CultureInfo;

        public NaturalComparer(CultureInfo cultureInfo)
        {
            _CultureInfo = cultureInfo;
        }

        public int Compare(string x, string y)
        {
            // simple cases
            if (x == y) // also handles null
                return 0;
            if (x == null)
                return -1;
            if (y == null)
                return +1;

            int ix = 0;
            int iy = 0;
            while (ix < x.Length && iy < y.Length)
            {
                if (Char.IsDigit(x[ix]) && Char.IsDigit(y[iy]))
                {
                    // We found numbers, so grab both numbers
                    int ix1 = ix++;
                    int iy1 = iy++;
                    while (ix < x.Length && Char.IsDigit(x[ix]))
                        ix++;
                    while (iy < y.Length && Char.IsDigit(y[iy]))
                        iy++;
                    string numberFromX = x.Substring(ix1, ix - ix1);
                    string numberFromY = y.Substring(iy1, iy - iy1);

                    // Pad them with 0's to have the same length
                    int maxLength = Math.Max(
                        numberFromX.Length,
                        numberFromY.Length);
                    numberFromX = numberFromX.PadLeft(maxLength, '0');
                    numberFromY = numberFromY.PadLeft(maxLength, '0');

                    int comparison = _CultureInfo
                        .CompareInfo.Compare(numberFromX, numberFromY);
                    if (comparison != 0)
                        return comparison;
                }
                else
                {
                    int comparison = _CultureInfo
                        .CompareInfo.Compare(x, ix, 1, y, iy, 1);
                    if (comparison != 0)
                        return comparison;
                    ix++;
                    iy++;
                }
            }

            // we should not be here with no parts left, they're equal
            Debug.Assert(ix < x.Length || iy < y.Length);

            // we still got parts of x left, y comes first
            if (ix < x.Length)
                return +1;

            // we still got parts of y left, x comes first
            return -1;
        }
    }
}

147
задан Raedwald 21 January 2016 в 12:04
поделиться