Descending Сортировать список в C # [дубликат]

Я предпочитаю использовать awk. Если есть только один столбец, используйте $0, иначе замените его на последний столбец.

Один из способов,

awk '{print $0, "string to append after each line"}' file > new_file

или это,

awk '$0=$0"string to append after each line"' file > new_file
910
задан poke 16 December 2015 в 10:45
поделиться

19 ответов

Самый простой способ, который я могу придумать, - использовать Linq:

List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
1337
ответ дан Kyle Alons 16 August 2018 в 10:00
поделиться
  • 1
    как я могу сортировать это в порядке убывания. – Bonus Kun 13 February 2013 в 19:03
  • 2
    @BonusKun List & lt; Order & gt; SortedList = objListOrder. OrderByDescending (o = & gt; o.OrderDate) .ToList (); – javajavajavajavajava 20 February 2013 в 16:18
  • 3
    обратите внимание, что это создает целый новый список со всеми элементами памяти, которые могут быть проблематичными с точки зрения производительности. – staafl 19 October 2013 в 20:25
  • 4
    @staafl будет listWithObjects = listWithObjects.OrderByDescending(o => o.Status).ToList(); достаточным для такого усилия? – Andrew Grinder 18 July 2014 в 16:52
  • 5
    @staafl Мы заказываем список ссылок на объекты, а не дублируем сами объекты, насколько мне известно. Хотя это удваивает память, используемую списком ссылок, это не так плохо, как фактически дублирование всех самих объектов, поэтому в большинстве сценариев за пределами тех, где мы имеем дело с огромными наборами данных и удерживаем их в памяти, уже проблема, тогда это должно быть достаточно. – Lazarus 22 April 2015 в 18:36

Чтобы сделать это без LINQ на .Net2.0:

List<Order> objListOrder = GetOrderList();
objListOrder.Sort(
    delegate(Order p1, Order p2)
    {
        return p1.OrderDate.CompareTo(p2.OrderDate);
    }
);

Если вы находитесь на .Net3.0, то ответ [LQH] LukeH - это то, что вы после .

Чтобы сортировать по нескольким свойствам, вы все равно можете сделать это в пределах делегата. Например:

orderList.Sort(
    delegate(Order p1, Order p2)
    {
        int compareDate = p1.Date.CompareTo(p2.Date);
        if (compareDate == 0)
        {
            return p2.OrderID.CompareTo(p1.OrderID);
        }
        return compareDate;
    }
);

Это даст вам восходящие даты с нисходящим порядком.

Тем не менее, я бы не рекомендовал прикреплять делегатов, поскольку это будет означать много мест без повторного использования кода. Вы должны реализовать IComparer и просто передать это до вашего метода Sort. См. здесь .

public class MyOrderingClass : IComparer<Order>
{
    public int Compare(Order x, Order y)
    {
        int compareDate = x.Date.CompareTo(y.Date);
        if (compareDate == 0)
        {
            return x.OrderID.CompareTo(y.OrderID);
        }
        return compareDate;
    }
}

И затем, чтобы использовать этот класс IComparer, просто создайте его и передайте его вашему методу Сортировка:

IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);
198
ответ дан Community 16 August 2018 в 10:00
поделиться
  • 1
    Было бы неплохо использовать Singleton для компаратора? – wonton 14 October 2013 в 02:04
  • 2
    Отличный ответ, и он должен быть правильным, поскольку он защищает повторную инициализацию исходного списка (который всегда будет делать версия LINQ), обеспечивая лучшую инкапсуляцию. – Jeb 30 September 2014 в 17:01
  • 3
    @wonton, no. Идея состоит в том, чтобы иметь различные реализации IComparer, предоставляя нам полиморфное поведение. – radarbob 16 October 2014 в 15:55
  • 4
    Работал для меня. Я опубликовал версию этого с настройками сортировки. – Jack Griffin 6 January 2015 в 14:51

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

objListOrder = GetOrderList()
                   .OrderBy(o => o.OrderDate)
                   .ToList();

objListOrder = GetOrderList()
                   .OrderBy(o => o.OrderId)
                   .ToList();
3
ответ дан Daniel A. White 16 August 2018 в 10:00
поделиться

Вы можете сделать что-то более общее в выборе свойств, но определенно о типе, который вы выбираете, в вашем случае «Заказ»:

записывать вашу функцию как общую:

public List<Order> GetOrderList<T>(IEnumerable<Order> orders, Func<Order, T> propertySelector)
        {
            return (from order in orders
                    orderby propertySelector(order)
                    select order).ToList();
        } 

, а затем использовать его следующим образом:

var ordersOrderedByDate = GetOrderList(orders, x => x.OrderDate);

Вы можете быть еще более общим и определить открытый тип для того, что вы хотите заказать:

public List<T> OrderBy<T,P>(IEnumerable<T> collection, Func<T,P> propertySelector)
        {
            return (from item in collection
                    orderby propertySelector(item)
                    select item).ToList();
        } 

и использовать его таким же образом:

var ordersOrderedByDate = OrderBy(orders, x => x.OrderDate);

Какой глупый ненужный сложный способ сделать стиль LINQ «OrderBy», но он может дать вам представление о том, как он может быть реализован в общий способ

3
ответ дан Danny Mor 16 August 2018 в 10:00
поделиться

Ни один из вышеперечисленных ответов не был достаточно общим для меня, поэтому я сделал это:

var someUserInputStringValue = "propertyNameOfObject i.e. 'Quantity' or 'Date'";
var SortedData = DataToBeSorted
                   .OrderBy(m => m.GetType()
                                  .GetProperties()
                                  .First(n => 
                                      n.Name == someUserInputStringValue)
                   .GetValue(m, null))
                 .ToList();

Осторожно на массивные массивы данных. Это простой код, но может вызвать у вас проблемы, если коллекция огромна, а тип объекта коллекции имеет большое количество полей. Время запуска - NxM, где:

N = # элементов в коллекции

M = # свойств в объекте

2
ответ дан itcropper 16 August 2018 в 10:00
поделиться

На основе Comparer GenericTypeTea: мы можем получить большую гибкость, добавив флаги сортировки:

public class MyOrderingClass : IComparer<Order> {  
    public int Compare(Order x, Order y) {  
        int compareDate = x.Date.CompareTo(y.Date);  
        if (compareDate == 0) {  
            int compareOrderId = x.OrderID.CompareTo(y.OrderID);  

            if (OrderIdDescending) {  
                compareOrderId = -compareOrderId;  
            }  
            return compareOrderId;  
        }  

        if (DateDescending) {  
            compareDate = -compareDate;  
        }  
        return compareDate;  
    }  

    public bool DateDescending { get; set; }  
    public bool OrderIdDescending { get; set; }  
}  

В этом сценарии вы должны создать экземпляр как MyOrderingClass явно (а не IComparer), чтобы установить его сортировку свойства:

MyOrderingClass comparer = new MyOrderingClass();  
comparer.DateDescending = ...;  
comparer.OrderIdDescending = ...;  
orderList.Sort(comparer);  
1
ответ дан Jack Griffin 16 August 2018 в 10:00
поделиться
var obj = db.Items.Where...

var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));
2
ответ дан Jevgenij Kononov 16 August 2018 в 10:00
поделиться

Выполнение этого без Linq, как вы сказали:

public class Order : IComparable
{
    public DateTime OrderDate { get; set; }
    public int OrderId { get; set; }

    public int CompareTo(object obj)
    {
        Order orderToCompare = obj as Order;
        if (orderToCompare.OrderDate < OrderDate || orderToCompare.OrderId < OrderId)
        {
            return 1;
        }
        if (orderToCompare.OrderDate > OrderDate || orderToCompare.OrderId > OrderId)
        {
            return -1;
        }

        // The orders are equivalent.
        return 0;
    }
}

Затем просто позвоните .sort () в свой список Orders

31
ответ дан Jimmy Hoffa 16 August 2018 в 10:00
поделиться
  • 1
    Сначала нужно проверить null на as. В чем смысл as, поскольку (ha, ha) (Order)obj выдает исключение, когда он терпит неудачу. if(orderToCompare == null) return 1;. – radarbob 16 October 2014 в 15:30
  • 2
    +1 для использования интерфейса, что делает код более легким в обслуживании и явно предоставляет возможности объекта. – AeonOfTime 6 November 2015 в 23:29
  • 3
    Если бы Билл и Тед когда-либо появлялись, я попрошу их вернуть меня к 16 октября 2014 года, чтобы я мог исправить свою ошибку выше - as возвращает null, если сбой происходит. Но, по крайней мере, нулевой тест прав. – radarbob 3 October 2017 в 06:03
  • 4
    @radarbob да .. упс. :) Но! Эта функция предназначена для автоматического использования по сортировке по списку, который является List<Order>, поэтому тип должен быть гарантированно соответствовать на as, поэтому в 2014 году вы, вероятно, не писали ошибку, чтобы избежать ненужной защиты заявление :) – Jimmy Hoffa 7 November 2017 в 17:01
  • 5
    должен быть гарантирован Интересный момент. Если он хорошо инкапсулирован так, что его нельзя назвать, кроме как передать List<Order>; но вы и я оба встретили программиста с самоинкапсулированными данными, у которого невысказанная презумпция есть «я пишу этот код, чтобы он не использовался неправильно». – radarbob 7 November 2017 в 22:31

Для использования CompareTo требуется любой, кто работает с типами NULL, Value.

objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));

0
ответ дан Jude 16 August 2018 в 10:00
поделиться

Если вам нужно отсортировать список на месте, вы можете использовать метод Sort , передав делегат Comparison<T> :

objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));

Если вы предпочитаете создавать новую, отсортированную последовательность, а не сортировать на месте, вы можете использовать метод LINQ OrderBy , как указано в других ответах.

503
ответ дан LukeH 16 August 2018 в 10:00
поделиться
  • 1
    Да, это «правильный». ответ и должен быть намного более эффективным, чем создание нового IEnumerable, а затем преобразование его в новый список. – Jonathan Wood 30 December 2015 в 18:11
  • 2
    Конечно, если вам нужна нисходящая сортировка, замените x и y на правую часть стрелки =>. – Jeppe Stig Nielsen 9 June 2016 в 08:13
  • 3
    Настоящий ответ, который фактически сортирует список на месте – Mitchell Currie 9 August 2016 в 01:09
  • 4
    @PimBrouwers Это лучший период опций. Даже если объем памяти, который вы используете, не является проблемой, это решение позволяет избежать ненужного распределения памяти, которое чрезвычайно дорого. Эта опция столь же проста и на порядок выше. – Cdaragorn 14 December 2016 в 21:58
  • 5
    @JonSchneider Для Nullable<> (возьмите DateTime? в качестве примера) вы можете использовать .Sort((x, y) => Nullable.Compare(x.OrderDate, y.OrderDate)), который будет обрабатывать нуль, как и все ненулевые значения. Это точно так же, как .Sort((x, y) => Comparer<DateTime?>.Default.Compare(x.OrderDate, y.OrderDate). – Jeppe Stig Nielsen 30 January 2017 в 12:39

Пожалуйста, позвольте мне заполнить ответ @LukeH с некоторым примером кода, поскольку я его протестировал. Я считаю, что это может быть полезно для некоторых:

public class Order
{
    public string OrderId { get; set; }
    public DateTime OrderDate { get; set; }
    public int Quantity { get; set; }
    public int Total { get; set; }

    public Order(string orderId, DateTime orderDate, int quantity, int total)
    {
        OrderId = orderId;
        OrderDate = orderDate;
        Quantity = quantity;
        Total = total;
    }
}

public void SampleDataAndTest()
{
    List<Order> objListOrder = new List<Order>();

    objListOrder.Add(new Order("tu me paulo ", Convert.ToDateTime("01/06/2016"), 1, 44));
    objListOrder.Add(new Order("ante laudabas", Convert.ToDateTime("02/05/2016"), 2, 55));
    objListOrder.Add(new Order("ad ordinem ", Convert.ToDateTime("03/04/2016"), 5, 66));
    objListOrder.Add(new Order("collocationem ", Convert.ToDateTime("04/03/2016"), 9, 77));
    objListOrder.Add(new Order("que rerum ac ", Convert.ToDateTime("05/02/2016"), 10, 65));
    objListOrder.Add(new Order("locorum ; cuius", Convert.ToDateTime("06/01/2016"), 1, 343));


    Console.WriteLine("Sort the list by date ascending:");
    objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));

    foreach (Order o in objListOrder)
        Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);

    Console.WriteLine("Sort the list by date descending:");
    objListOrder.Sort((x, y) => y.OrderDate.CompareTo(x.OrderDate));
    foreach (Order o in objListOrder)
        Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);

    Console.WriteLine("Sort the list by OrderId ascending:");
    objListOrder.Sort((x, y) => x.OrderId.CompareTo(y.OrderId));
    foreach (Order o in objListOrder)
        Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);

    //etc ...
}
3
ответ дан molbalga 16 August 2018 в 10:00
поделиться

Вот общий метод расширения LINQ, который не создает дополнительную копию списка:

public static void Sort<T,U>(this List<T> list, Func<T, U> expression)
    where U : IComparable<U>
{
    list.Sort((x, y) => expression.Invoke(x).CompareTo(expression.Invoke(y)));
}

Чтобы использовать его:

myList.Sort(x=> x.myProperty);

Недавно я построил этот дополнительный один, который принимает ICompare<U>, так что вы можете настроить сравнение. Это пригодилось, когда мне нужно было сделать естественную сортировку строки:

public static void Sort<T, U>(this List<T> list, Func<T, U> expression, IComparer<U> comparer)
    where U : IComparable<U>
{    
    list.Sort((x, y) => comparer.Compare(expression.Invoke(x), expression.Invoke(y)));
}
5
ответ дан Peter 16 August 2018 в 10:00
поделиться
  • 1
    Я реализовал это, отлично работает. Я добавил «isAscending = true». параметр. Чтобы сортировать по убыванию, просто поменяйте x и y вокруг двух методов Invoke (). Благодарю. – Rob L 5 March 2014 в 22:58
  • 2
    Если вы просто собираетесь скомпилировать выражение, вы можете просто принять делегата для начала. Кроме того, этот подход имеет серьезные проблемы, если селектор вызывает побочные эффекты, является дорогостоящим для вычисления или не является детерминированным. Правильная сортировка, основанная на выбранном выражении, должна вызывать селектор не более одного раза за элемент в списке. – Servy 8 April 2014 в 20:06
  • 3
    @Servy - это все действительные точки, но я буду честен, я не уверен, как реализовать некоторые из ваших соблазнов (особенно, чтобы остановить селектор от побочных эффектов ...?). Я изменил их на делегатов. Если вы знаете, как внести некоторые из этих изменений, я был бы рад, если бы вы отредактировали мой код. – Peter 8 April 2014 в 22:06
  • 4
    @Peter Вы не можете помешать делегатам вызвать побочные эффекты. Что вы можете сделать, так это убедиться, что они никогда не вызываются более одного раза для каждого объекта, это означает вычисление значений для каждого объекта, сохранение пар объектов / прогнозируемых значений, а затем сортировку , что . OrderBy делает все это внутренне. – Servy 8 April 2014 в 22:08
  • 5
    Еще один хороший способ написать метод расширения void в этом духе: static class Extensions { public static void SortBy<TSource, TKey>(this List<TSource> self, Func<TSource, TKey> keySelector) { self.SortBy(keySelector, Comparer<TKey>.Default); } public static void SortBy<TSource, TKey>(this List<TSource> self, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) { self.Sort((x, y) => comparer.Compare(keySelector(x), keySelector(y))); } } Может быть дополнен методом SortByDescending. @ Замечания Servy применимы и к моему коду! – Jeppe Stig Nielsen 30 January 2017 в 12:59

Использовать LiNQ OrderBy

List<Order> objListOrder=new List<Order> ();
    objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();
1
ответ дан Pranay Rana 16 August 2018 в 10:00
поделиться

Самый простой способ упорядочить список - использовать OrderBy

 List<Order> objListOrder = 
    source.OrderBy(order => order.OrderDate).ToList();

Если вы хотите заказать несколько столбцов, например, следующий SQL Query.

ORDER BY OrderDate, OrderId

Чтобы достичь это вы можете использовать ThenBy, как показано ниже.

  List<Order> objListOrder = 
    source.OrderBy(order => order.OrderDate).ThenBy(order => order.OrderId).ToList();
77
ответ дан PSK 16 August 2018 в 10:00
поделиться

Классическое объектно-ориентированное решение

Сначала я должен напомнить об удивительности LINQ ... Теперь, когда у нас это получилось

Вариант на JimmyHoffa ответ. С помощью дженериков параметр CompareTo становится безопасным по типу.

public class Order : IComparable<Order> {

    public int CompareTo( Order that ) {
        if ( that == null ) return 1;
        if ( this.OrderDate > that.OrderDate) return 1;
        if ( this.OrderDate < that.OrderDate) return -1;
        return 0;
    }
}

// in the client code
// assume myOrders is a populated List<Order>
myOrders.Sort(); 

Эта сортировка по умолчанию пригодна для повторного использования, конечно. То есть каждому клиенту не требуется избыточно переписывать логику сортировки. Переключение «1» и «-1» (или логические операторы, ваш выбор) отменяет порядок сортировки.

20
ответ дан radarbob 16 August 2018 в 10:00
поделиться
  • 1
    Простой подход для сортировки объектов в списке. Но я не понимаю, почему вы возвращаете 1, если (что == null)? – Loc Huynh 22 June 2017 в 20:55
  • 2
    это означает, что объект this больше нуля. Для целей сортировки ссылка на нулевой объект "меньше, чем" this объект. Именно так я решил определить, как сортируются нули. – radarbob 23 June 2017 в 02:03

// Полностью общая сортировка для использования с gridview

public List<T> Sort_List<T>(string sortDirection, string sortExpression, List<T> data)
    {

        List<T> data_sorted = new List<T>();

        if (sortDirection == "Ascending")
        {
            data_sorted = (from n in data
                              orderby GetDynamicSortProperty(n, sortExpression) ascending
                              select n).ToList();
        }
        else if (sortDirection == "Descending")
        {
            data_sorted = (from n in data
                              orderby GetDynamicSortProperty(n, sortExpression) descending
                              select n).ToList();

        }

        return data_sorted;

    }

    public object GetDynamicSortProperty(object item, string propName)
    {
        //Use reflection to get order type
        return item.GetType().GetProperty(propName).GetValue(item, null);
    }
15
ответ дан roger 16 August 2018 в 10:00
поделиться
  • 1
    Или, вы знаете, data.OrderBy(). Немного легче, чем изобретать колесо. – gunr2171 13 June 2013 в 02:41
  • 2
    Идея заключается в том, что это будет работать с любым типом объекта. Где как OrderBy () работает только с сильно типизированными объектами. – roger 1 October 2013 в 07:01
  • 3
    Thx много. На мой взгляд, самое простое и удобное решение для сортировки данных сетки! – kostas ch. 29 January 2015 в 07:45

Улучшена версия Роджера.

Проблема с GetDynamicSortProperty заключается в том, что они получают только имена свойств, но что произойдет, если в GridView мы используем NavigationProperties? он отправит исключение, так как находит NULL.

Пример:

«Employee.Company.Name;» сбой ... поскольку разрешает только «Name» в качестве параметра получить его значение.

Вот улучшенная версия, которая позволяет нам сортировать по свойствам навигации.

public object GetDynamicSortProperty(object item, string propName)
    {
        try
        {                 
            string[] prop = propName.Split('.'); 

            //Use reflection to get order type                   
            int i = 0;                    
            while (i < prop.Count())
            {
                item = item.GetType().GetProperty(prop[i]).GetValue(item, null);
                i++;
            }                     

            return item;
        }
        catch (Exception ex)
        {
            throw ex;
        }


    } 
3
ответ дан user1013375 16 August 2018 в 10:00
поделиться

С точки зрения производительности лучше всего использовать отсортированный список, чтобы данные сортировались по мере добавления к результату. Другие подходы нуждаются, по крайней мере, в одной дополнительной итерации по данным, и большинство из них создают копию данных, поэтому будет затронута не только производительность, но и использование памяти. Не может быть проблемой с несколькими сотнями элементов, но будет с тысячами, особенно в тех службах, где одновременно может выполняться сортировка нескольких параллельных запросов. Посмотрите на пространство имен System.Collections.Generic и выберите класс с сортировкой вместо списка.

И избегайте общих реализаций, используя отражение, когда это возможно, это также может вызвать проблемы с производительностью.

0
ответ дан user3285954 16 August 2018 в 10:00
поделиться
  • 1
    Как это может быть более результативным? Вставка данных в отсортированный список - O (n), поэтому добавление n элементов - O (n ^ 2). Что пытается добавить много параллельных элементов? Бывают ситуации, когда у вас есть дополнительные циклы CPU для записи при добавлении элементов, но это не является хорошим общим решением. – John La Rooy 5 December 2017 в 21:41
//Get data from database, then sort list by staff name:

List<StaffMember> staffList = staffHandler.GetStaffMembers();

var sortedList = from staffmember in staffList
                 orderby staffmember.Name ascending
                 select staffmember;
3
ответ дан Waqas Ahmed 16 August 2018 в 10:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: