Перечислить сложную сортировку <string>

У меня размер List<string>, например XS, S, M, L, XL, XXL, UK 10, UK 12 и т.д.

Что я хочу, так это заставить порядок быть выше, независимо от порядка элементов в списке, я думаю, что мне нужен оператор IComparable, но не уверен.

В идеале я хочу иметь другой список с правильным порядком, в котором он может ссылаться на "место" в списке и пересортировать его, если он не существует, он по умолчанию будет использовать A-Z

Ответ 1

Создайте массив размеров в том порядке, в котором вы хотите, и затем сортируйте рубашки по их размерам в этом массиве:

string[] sizes = new [] {"XS", "S", "M", "L", "XL", "XXL", "UK 10", "UK 12"};

var shirtsInOrder = shirts
                        .OrderBy(s=>sizes.Contains(s) ? "0" : "1")  // put unmatched sizes at the end
                        .ThenBy(s=>Array.IndexOf(sizes,s))  // sort matches by size
                        .ThenBy(s=>s); // sort rest A-Z

Ответ 2

var order = new string[] { "XS", "S", "M", "L", "XL", "XXL", "UK10", "UK12" };

var orderDict = order.Select((c, i) => new { sze = c, ord = i })
            .ToDictionary(o => o.sze, o => o.ord);

var list = new List<string> { "S", "L", "XL", "L", "L", "XS", "XL" };
var result = list.OrderBy(item => orderDict[item]);

Ответ 3

Вы можете напрямую использовать OrderByDescending + ThenByDescending:

sizes.OrderByDescending(s => s == "XS")
     .ThenByDescending( s => s == "S")
     .ThenByDescending( s => s == "M")
     .ThenByDescending( s => s == "L")
     .ThenByDescending( s => s == "XL")
     .ThenByDescending( s => s == "XXL")
     .ThenByDescending( s => s == "UK 10")
     .ThenByDescending( s => s == "UK 12")
     .ThenBy(s => s);

Я использую ...Descending, так как a true похож на 1, тогда как a false равно 0.

Ответ 4

Вы также можете создать другой список и использовать делегат для использования с сортировкой, где вы возвращаете, если индекс size1 > index size2.

Ответ 5

Вы также можете сделать что-то вроде этого:

public class ShirtComparer : IComparer<string>
{
    private static readonly string[] Order = new[] { "XS", "S", "M", "L", "XL", "XXL", "UK10", "UK12" };

    public int Compare(string x, string y)
    {
        var xIndex = Array.IndexOf(Order, x);
        var yIndex = Array.IndexOf(Order, y);

        if (xIndex == -1 || yIndex == -1) 
            return string.Compare(x, y, StringComparison.Ordinal);

        return xIndex - yIndex;
    }
}

Использование:

var list = new List<string> { "S", "L", "XL", "L", "L", "XS", "XL", "XXXL", "XMLS", "XXL", "AM19" };
var result = list.OrderBy(size => size, new ShirtComparer());

Он также должен по умолчанию использовать A-Z для значений, не входящих в список...