Сортировка списка <> по свойству объекта

1

Мне нужно отсортировать список объектов по одному из свойств объекта, но это строка, которая должна быть отсортирована так, как если бы она была целым числом. Объекты являются обычными объектами "Свойства", в которых имя свойства (property.Name) является строкой, однако 90% имен свойств фактически являются числами, а остальные 10% - именами/буквами (следовательно, в то время как сама переменная должна быть строка, а не целое число).

Я знаю, что могу использовать

propertyList.OrderBy(x => x.Name)

... но это будет сортировать его, глядя на него, как будто это строка (т.е. 15000 "больше", чем 20).

Для сортировки я уже разделил список на два отдельных списка (один из которых содержит все имена с именами свойств, которые содержат буквы, а другой - те, которые могут быть преобразованы в целые числа), но я не знаю, как сортировать список "integer".

Я пробовал это, и он не работает, но есть ли что-то вроде этого, которое я могу использовать?

propertyList.OrderBy(x => Convert.ToInt32(x.Name))
  • 2
    Вы сохраняете результат OrderBy(...) ? OrderBy не выполняет сортировку на месте, вместо этого он возвращает отсортированное представление IEnumerable<T> ваших данных.
  • 0
    Я отредактировал ваш заголовок. Пожалуйста, смотрите: « Должны ли вопросы включать« теги »в их заголовки? », Где консенсус «нет, они не должны».
Теги:
object
list

2 ответа

4

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

IEnumerable<TItem> sorted = propertyList.OrderBy( x => {
    Int32 asInt;
    if( Int32.TryParse( x.Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out asInt ) ) {
        return asInt;
    }
    if( x.Name.Length > 0 ) return (Int32)x.Name[0];
    return 0;
});

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

class NameComparer : IComparer<String> {
    public Int32 Compare(String x, String y) {
        // put Name comparison logic here
    }
}

IEnumerable<TItem> sorted = propertyList.OrderBy( x => x.Name, new NameComparer() );
0

Непонятно, что вы на самом деле хотите здесь. Вы хотите упорядоченное представление исходных данных? Или вы действительно хотите изменить исходные данные так, чтобы они были заказаны?

Если первый, то метод OrderBy() - это то, что вы хотите. Похоже, вы прекрасно сортируете числовые имена отдельно от нечисловых, но в этом случае неясно, что вы подразумеваете под "не работает", когда вы попробовали свой второй пример кода. Это выражение должно работать нормально и обеспечит упорядоченное представление ваших данных. Например

foreach (var x in propertyList.OrderBy(x => int.Parse(x.Name))
{
    // do something with the ordered elements
}

Если вы хотите, чтобы вы действительно заказывали исходные данные, вы можете просто использовать метод List<T>.Sort():

propertyList.Sort((x, y) => int.Parse(x.Name).CompareTo(int.Parse(y.Name));

Обратите внимание, что в примере List<T> преобразование из строки в int выполняется повторно. Это не должно быть проблемой для относительно небольших коллекций, но если производительность становится проблемой, то OrderBy() использовать метод LINQ OrderBy() (который кэширует ключи для вас). Вы можете использовать ToList() с OrderBy() чтобы вернуть результат в List<T>.

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

  • 0
    Note that in both of the above examples, the conversion from string to int is done repeatedly : не так, Enumerable.OrderBy кэширует ключ (по крайней мере, в наши дни; возможно, это не всегда было так).
  • 0
    Ах, отлично. Полезно знать ... спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню