C # OrderBy DateTime? без пустых значений, имеющих приоритет [дубликат]

Я пытаюсь сортировать список продуктов по их цене.

В результирующем наборе необходимо перечислить продукты по цене от низкого до высокого по столбцу LowestPrice. Однако этот столбец имеет значение NULL.

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

var products = from p in _context.Products
   where p.ProductTypeId == 1
   orderby p.LowestPrice.HasValue descending
   orderby p.LowestPrice descending
   select p;

// returns:    102, 101, 100, null, null

Однако я не могу понять, как отсортировать его в порядке возрастания.

// i'd like: 100, 101, 102, null, null
92
задан JasonMArcher 3 October 2014 в 22:37
поделиться

8 ответов

Попробуйте поместить оба столбца в том же порядке.

orderby p.LowestPrice.HasValue descending, p.LowestPrice

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

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

120
ответ дан DaveShaw 20 August 2018 в 20:40
поделиться
  • 1
    веселит. так просто, я чувствую себя идиотом: P – sf. 23 June 2011 в 23:50
  • 2
    Обычная ошибка, люди делают то же самое с синтаксисом Lambda - используя .OrderBy дважды вместо .ThenBy. – DaveShaw 23 June 2011 в 23:51
  • 3
    Этот обработанный для заказа полей со значениями сверху и нулевых полей внизу i использовал это: orderby p.LowestPrice == null, p.LowestPrice ascending Надежда помогает кому-то. – stom 27 September 2015 в 11:32
  • 4
    @DaveShaw спасибо за отзыв - особенно комментарий один - очень аккуратный - люблю его – Demetris Leptos 3 December 2016 в 11:50

Это то, что я придумал, потому что я использую методы расширения, а также мой элемент - это строка, поэтому нет .HasValue:

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString)

Это работает с объектами LINQ 2 в памяти. Я не тестировал его с помощью EF или любого DB ORM.

5
ответ дан AaronLS 20 August 2018 в 20:40
поделиться

Это действительно помогает понять синтаксис запроса LINQ и то, как он переводится на вызовы метода LINQ.

Оказывается, что

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending
               orderby p.LowestPrice descending
               select p;

будет переведен компилятором на

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .OrderByDescending(p => p.LowestPrice)
                       .Select(p => p);

Это решительно не то, что вы хотите. Это сортирует по Product.LowestPrice.HasValue в порядке descending, а затем повторно сортирует всю коллекцию по Product.LowestPrice в порядке descending.

Вы хотите

var products = _context.Products
                       .Where(p => p.ProductTypeId == 1)
                       .OrderByDescending(p => p.LowestPrice.HasValue)
                       .ThenBy(p => p.LowestPrice)
                       .Select(p => p);

которую вы можете получить с помощью синтаксиса запроса

var products = from p in _context.Products
               where p.ProductTypeId == 1
               orderby p.LowestPrice.HasValue descending,
                       p.LowestPrice
               select p;

. Подробнее о переводах из синтаксиса запроса в вызовы методов см. спецификацию языка. Шутки в сторону. Прочтите.

65
ответ дан abc123 20 August 2018 в 20:40
поделиться
  • 1
    +1 или просто ... не пишите синтаксис запроса LINQ :) Хорошее объяснение, тем не менее – sehe 24 June 2011 в 00:12

У меня есть другой вариант в этой ситуации. Мой список является objList, и я должен заказать, но нули должны быть в конце. мое решение:

var newList = objList.Where(m=>m.Column != null)
                     .OrderBy(m => m.Column)
                     .Concat(objList.where(m=>m.Column == null));
14
ответ дан Gurgen Hovsepyan 20 August 2018 в 20:40
поделиться
  • 1
    Это может работать в сценариях, где требуется результат с другими значениями, например 0 вместо нуля. – Naresh Ravlani 1 September 2016 в 09:24
  • 2
    Да. Просто замените значение null на 0. – Gurgen Hovsepyan 1 September 2016 в 13:04

Решение для строковых значений действительно странно:

.OrderBy(f => f.SomeString == null).ThenBy(f => f.SomeString) 

Единственная причина, по которой это работает, состоит в том, что первое выражение OrderBy(), sort bool: true / false , false Результат сначала следует результатом true (nullables) и ThenBy() сортирует ненулевые значения в алфавитном порядке.

Итак, я предпочитаю делать что-то более читаемое, например следующее:

.OrderBy(f => f.SomeString ?? "z")

Если SomeString равно null, он будет заменен на "z", а затем отсортировать все по алфавиту.

ПРИМЕЧАНИЕ. Это не окончательное решение, поскольку "z" идет первым, чем z-значения, такие как zebra.

UPDATE 9/6/2016 - О комментарии @jornhd, it на самом деле это хорошее решение, но оно все еще немного сложное, поэтому я рекомендую его обернуть в классе Extension, например:

public static class MyExtensions
{
    public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, string> keySelector)
    {
        return list.OrderBy(v => keySelector(v) != null ? 0 : 1).ThenBy(keySelector);
    }
}

И просто используйте его как:

var sortedList = list.NullableOrderBy(f => f.SomeString);
10
ответ дан Jaider 20 August 2018 в 20:40
поделиться
  • 1
    Я думаю, что это более читаемо, без неприятной константы: .OrderBy (f = & gt; f.SomeString! = Null? 0: 1) .ThenBy (f = & gt; f.SomeString) – jornhd 4 May 2016 в 11:44

Ниже приведен метод расширения для проверки нулевого значения, если вы хотите сортировать дочернее свойство keySelector.

public static IOrderedEnumerable<T> NullableOrderBy<T>(this IEnumerable<T> list, Func<T, object> parentKeySelector, Func<T, object> childKeySelector)
{
    return list.OrderBy(v => parentKeySelector(v) != null ? 0 : 1).ThenBy(childKeySelector);
}

И просто используйте его как:

var sortedList = list.NullableOrderBy(x => x.someObject, y => y.someObject?.someProperty);
0
ответ дан Noel Widmer 20 August 2018 в 20:40
поделиться

мое решение:

Array = _context.Products.OrderByDescending(p => p.Val ?? float.MinValue)
8
ответ дан RTKV 20 August 2018 в 20:40
поделиться

Я пытался найти решение LINQ для этого, но не смог его решить из ответов.

Мой последний ответ был:

.OrderByDescending(p.LowestPrice.HasValue).ThenBy(p.LowestPrice)
4
ответ дан user1 20 August 2018 в 20:40
поделиться
Другие вопросы по тегам:

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