Zaur Bahramov Ответов: 4

Заказать список в C#


Привет!

У меня есть следующий список:

var arrayList = new List<List<int>>();
List<int> 
      row = new List<int>() {5, 9, 17, 40, 99};
      arrayList.Add(row.ToList());
      row = new List<int>() {12, 24, 30, 45, 80};
      arrayList.Add(row.ToList());
      row = new List<int>() {5, 9, 17, 16, 99};
      arrayList.Add(row.ToList());
      row = new List<int>() {1, 5, 8, 15, 25};
      arrayList.Add(row.ToList());


Мне нужно отсортировать этот список так, чтобы получить следующий результат:
1 5 8 15 25
5 9 17 16 99
5 9 17 40 99
12 24 30 45 80


Итак, на самом деле мне нужно упорядочить список сначала по столбцам, а затем по значениям строк. Что-то похожее на пользовательскую сортировку в Excel.

Как я могу выполнить эту задачу?

Заранее благодарю вас!

Что я уже пробовал:

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

Patrice T

покажите свою работу и объясните, где вы застряли.

BillWoodruff

- Я придумал, как сортировать значения по возрастанию в строках списка."

покажите свой код для этого, и у нас может быть ключ к тому, как вам помочь.

этот ряд : 5 9 17 16 99

не сортируется ... предполагая, что вы хотите его в порядке возрастания

4 Ответов

Рейтинг:
34

BillWoodruff

using System.Linq; // required:

List<List<int>> list = new List<List<int>>
{
   new List<int> {5, 9, 17, 40, 99},
   new List<int> {12, 24, 30, 45, 80},
   new List<int>() {5, 9, 17, 16, 99},
   new List<int>() {0, 9, 17, 16, 0},
   new List<int>() {129, 5, 8, 15, 25}
};
Начните с упорядочивания каждой строки:
IEnumerable<List<int>> rlist = list.Select(
    lst => lst.OrderBy(i => i).ToList()
);
Затем упорядочите значения по индексу #0 в каждой строке:
List<List<int>> sortedList = = rlist.OrderBy(lst => lst[0]).ToList();
Вы можете связать их вместе:
var rlist = list
    .Select(lst => lst.OrderBy(i => i).ToList())
        .OrderBy(lst => lst[0])
    .ToList();


RickZeeland

5d :)

Maciej Los

Превосходно!

Zaur Bahramov

Он работает, но сортируется только по lst[0], первому полю строки, однако он не работает при сортировке по второму, третьему, четвертому и пятому полю.
Результатом этого кода является:
0 | 0 | 9 | 16 | 17 | =
5 | 9 | 17 | 40 | 99 |
5 | 9 | 16 | 17 | 99 |
5 | 8 | 15 | 25 | 129 |
12 | 24 | 30 | 45 | 80 |

Но все должно быть именно так:
0 | 0 | 9 | 16 | 17 | =
5 | 8 | 15 | 25 | 129 |
5 | 9 | 16 | 17 | 99 |
5 | 9 | 17 | 40 | 99 |
12 | 24 | 30 | 45 | 80 |

Zaur Bahramov

Я пытался сделать что-то вроде следующего, но это не работает, так как в этом случае он сортирует по последнему полю...
for (int i = 0; i<5; i++) {
sortedList = rlist.OrderBy(lst => lst[i]).Список();
}

Zaur Bahramov

sortedList = rlist.OrderBy(lst => lst[0]).ThenBy(lst => lst[1]).ThenBy(lst => lst[2]).ThenBy(lst => lst[3]).ThenBy(lst => lst[4]).Список();

Я использовал thenby, и результат в порядке. Однако если количество полей в строке не 5, как в приведенном выше примере, а произвольно, то как перебрать ThenBy, чтобы продолжить сортировку по каждому столбцу, начиная с первого?

BillWoodruff

Вам всегда придется иметь дело с данными, которые не являются регулярными.

Все проблемы, которые вы поднимаете, могут быть решены только тем, что вы приложите усилия, чтобы понять Linq и как его использовать. Для большинства из нас (особенно если у вас нет опыта работы с SQL-запросами) существует крутая кривая обучения.

Сайт Linqpad: https://www.linqpad.net/ дает вам отличный способ практиковаться в режиме онлайн и наблюдать за тем, что происходит при выполнении Linq.

Помощью linqpad находится в ведении Albihari, и их книги по LINQ-это хорошие ресурсы:
https://www.amazon.com/BenAlbahari/e/B001IO9OIQ/ref=dp_byline_cont_book_1

Здесь, на CP, есть хорошие статьи/учебные пособия по Linq.

Изучайте, экспериментируйте, наблюдайте, учитесь: повторяйте :)

твое здоровье, Билл

Рейтинг:
2

RickZeeland

Взгляните на это Интерфейс icomparable вот вам пример:
https://www.dotnetperls.com/icomparable[^]


BillWoodruff

это действительно смутное предположение, учитывая сложность цели ОП множественного рода.

RickZeeland

Просто будучи более строгим, нехорошо писать весь код для них, так они не будут учиться :)
Если вы внимательно посмотрите на пример, то увидите, что он делает именно то, что здесь требуется, это гибкий способ сортировки по нескольким значениям.

BillWoodruff

Честный ответный удар ! Я действительно читал опубликованный вами пример, который иллюстрирует интересную технику, когда в рамках одной сортировки вы переключаете критерий сортировки в методе CompareTo. Однако я не вижу никакого отношения к этому вопросу, который, имхо, требует двух отдельных видов.

к вашему сведению: было бы "неплохо", если бы Linq мог быть проще, не требуя многократных вызовов 'ToList()

Рейтинг:
0

John Parker

Привет,
Это всего лишь идея, но вы можете объединить значения в каждой строке в сопоставимые строки и просто отсортировать этот список строк.
Затем вы можете преобразовать результат обратно в целые числа, если хотите.


var arrayList = new List<List<int>>();
List<int> row = new List<int>() { 5, 9, 17, 40, 99 };
arrayList.Add(row.ToList());
row = new List<int>() { 12, 24, 30, 45, 80 };
arrayList.Add(row.ToList());
row = new List<int>() { 5, 9, 17, 16, 99 };
arrayList.Add(row.ToList());
row = new List<int>() { 1, 5, 8, 15, 25 };
arrayList.Add(row.ToList());

// maximum number of digits in input numbers
int maxDigits = 2;

// build list of strings, each a concatenation of numbers in row, left padded with "0"s
List<string> stringList = new List<string>();
foreach (List<int> dataRow in arrayList)
{
    string rowStr = "";
    foreach (int value in dataRow) rowStr += value.ToString().PadLeft(maxDigits, '0');
    stringList.Add(rowStr);
}

Console.WriteLine("input converted to list of strings:");
foreach (var s in stringList) Console.WriteLine(s);
Console.WriteLine();

// sort list of strings
stringList.Sort();

Console.WriteLine("sorted list of strings:");
foreach (var s in stringList) Console.WriteLine(s);


Выход:

input converted to list of strings:
0509174099
1224304580
0509171699
0105081525

sorted list of strings:
0105081525
0509171699
0509174099
1224304580
Press any key to continue . . .


Рейтинг:
0

Richard Deeming

Если я понял, что вы пытаетесь сделать, вам нужно реализовать обычай IComparer<T>[^] для сортировки списка:

public sealed class ListComparer<T> : IComparer<IReadOnlyList<T>> where T : IComparable
{
    public int Compare(IReadOnlyList<T> left, IReadOnlyList<T> right)
    {
        if (left is null) return right is null ? 0 : -1;
        if (right is null) return 1;
        
        var innerComparer = Comparer<T>.Default;
        int count = Math.Min(left.Count, right.Count);
        for (int index = 0; index < count; index++)
        {
            int result = innerComparer.Compare(left[index], right[index]);
            if (result != 0) return result;
        }
        
        return left.Count.CompareTo(right.Count);
    }
}
Имея это на месте, вы можете легко отсортировать свой список:
var list = new List<List<int>>
{
    new List<int> { 5, 9, 17, 40, 99 },
    new List<int> { 12, 24, 30, 45, 80 },
    new List<int> { 5, 9, 17, 16, 99 },
    new List<int> { 1, 5, 8, 15, 25 }
};

// Option 1: sort in-place:
list.Sort(new ListComparer<int>());

// Option 2: use LINQ:
var sortedList = list.OrderBy(l => l, new ListComparer<int>()).ToList();
Результат в любом случае соответствует желаемому результату вашего вопроса.

Этот компаратор будет работать со списками разной длины; если один список равен другому списку с добавлением некоторых дополнительных элементов, то более длинный список будет отсортирован после более короткого.