Как сортировать по 2 различным правилам в List

#c# #list #sorting

#c# #Список #сортировка

Вопрос:

Мне нужно отсортировать List<string> следующие 2 правила.

Мой string элемент всегда будет отформатирован как XXXnnnnE или XXXnnnnD где X прописные буквы от A до Z и n цифры от 0 до 9.

Я хочу отсортировать свой список в алфавитном порядке, но я хочу E , чтобы строка предшествовала D строке, как показано ниже

 DFG0001D
AWK0007E
ORK0127E
AWK0007D
DFG0001E
ORK0127D
  

необходимо отсортировать как

 AWK0007E
AWK0007D
DFG0001E
DFG0001D
ORK0127E
ORK0127D
  

Как я мог этого добиться?

Спасибо за помощь

Ответ №1:

Вот фрагмент, как вы можете сделать это с помощью Linq OrderBy, а затем убывающих операций:

 string[] arr = { "DFG0001D", "AWK0007E", "ORK0127E", "AWK0007D", "DFG0001E", "ORK0127D" };

arr = arr
   .OrderBy(r => r.Substring(0, 7))
   .ThenByDescending(s => s.Substring(7, 1))
   .ToArray();
  

Ответ №2:

вы можете использовать пользовательский делегат и сравнить первые 3 символа и последний:

 List<string> x = new List<string>();
x.Add("DFG0001D");
x.Add("AWK0007E");
x.Add("ORK0127E");
x.Add("AWK0007D");
x.Add("DFG0001E");
x.Add("ORK0127D");

x.Sort(delegate(string c1, string c2) { 
string a = c1.Substring(0, 3) c1.Substring(c1.Length-1, 1);
string b = c2.Substring(0, 3) c2.Substring(c2.Length-1, 1);
return (a.CompareTo(b)); 

});

Console.WriteLine("After sort...");
foreach (string i in x)
{
    Console.WriteLine(i);
}
  

Пример скрипки: https://dotnetfiddle.net/YAzvB4

Комментарии:

1. Отличное решение, но почему бы просто не создать делегат с лямбда-синтаксисом? Т.е. (c1, c2) => {...}

2. После тестирования этот код, похоже, не работает. Элементы сортируются только по алфавиту. After sort... AWK0007D AWK0007E DFG0001D DFG0001E ORK0127D ORK0127E

Ответ №3:

     var list = new List<string>{
        "DFG0001D",
        "AWK0007E",
        "ORK0127E",
        "AWK0007D",
        "DFG0001E",
        "ORK0127D"
    };

    list.Sort((str1, str2) => {
        var eq = string.Compare(str1.Substring(0, str1.Length - 1), str2.Substring(0, str2.Length - 1));
        if (eq == 0)
            eq = string.Compare(str2[str2.Length - 1].ToString(), "E");
        return eq; 
    });
    foreach (var str in list)
        Console.WriteLine(str);
  

Вывод:

 AWK0007E
AWK0007D
DFG0001E
DFG0001D
ORK0127E
ORK0127D
  

Ответ №4:

просто реализуйте свой собственный компаратор следующим образом:

 class CustomStringComparer : IComparer<string>
{
    private readonly IComparer<string> _baseComparer;
    public CustomStringComparer(IComparer<string> baseComparer)
    {
        _baseComparer = baseComparer;
    }

    public int Compare(string x, string y)
    {
        // strings are completely same
        if (_baseComparer.Compare(x, y) == 0)
        {
            return 0;
        }

        // strings are completely same except last char
        if (_baseComparer.Compare(x.Substring(0, x.Length - 2), y.Substring(0, y.Length - 2)) == 0)
        {
            // if last char is E then win
            return x.Last() == 'E' ? -1 : 1;
        }
        // defaut compare everything else
        return _baseComparer.Compare(x, y);
    }
}
  

Тогда вы сможете это сделать:

 static void Main(string[] args)
    {
        List<string> list = new List<string>()
        {
            "DFG0001D",
            "AWK0007E",
            "ORK0127E",
            "AWK0007D",
            "DFG0001E",
            "ORK0127D"
        };
        list.Sort(new CustomStringComparer(StringComparer.CurrentCulture));
        foreach (var item in list)
        {
            Console.WriteLine(item);
        }
    }
  

И вывод такой:

 AWK0007E
AWK0007D
DFG0001E
DFG0001D
ORK0127E
ORK0127D