#c#
#c#
Вопрос:
Мне интересно, выполняет ли список автоматическую сортировку или что-то в этом роде?
У меня есть
List<MyClass> myClass = new List<MyClass>()
myClass.Add(anotherClass);
myClass.Add(anotherClass2);
myClass.Add(anotherClass3);
myClass.Add(anotherClass4);
Итак, все они являются объектом MyClass. В нем есть что-то вроде этого
public class MyClass
{
public string type {get; set;}
public string title {get; set;}
}
List<MyClass> first = myClass .where(x => x.type == "first").toList();
List<MyClass> second = myClass .where(x => x.type == "second").toList();
first.Sort((x, y) => string.Compare(x.title, y.title));
second.Sort((x, y) => string.Compare(x.Title, y.Title));
myClass.Clear();
myClass.AddRange(first);
myClass.AddRange(second);
Итак, мой реальный код выглядит примерно так, за исключением того, что «MyClass» более сложный, и я использую их в цикле foreach.
Когда я делаю first.Sort() и second.Sort () все мои объекты расположены в правильном порядке на основе заголовка. Когда я очищаю и добавляю «первые» объекты в первый, а затем «второй» объект second, это разрушает мою сортировку.
Мне нужно, чтобы объекты с типом «first» были отсортированы перед объектами с типами «second».
Итак, скажем, у меня есть
A - first
B - second
C - first
D - second
это было бы
A
C
B
D
Я получаю
A - First
B - second
C - First
D - second
Ответ №1:
Нет, List<T>
его элементы всегда сохраняются в том порядке, в котором вы их добавляете, если вы явно не вставляете их в определенные позиции.
Однако вы можете попросить его отсортировать и предоставить пользовательское сравнение для сортировки — как вы уже сделали.
Похоже, вы делаете правильную вещь для того, что, по вашему описанию, вы хотите. Если бы я взял всех мужчин в вагоне поезда, в котором я сижу, упорядочил их по возрасту и создал из этого один список, затем сделал то же самое для женщин и, наконец, использовал:
List<Person> allPeople = new List<Person>();
allPeople.AddRange(menSortedByAge);
allPeople.AddRange(womenSortedByAge);
Я бы не стал сортировать всех по возрасту — я бы получил всех мужчин (отсортированных по возрасту), а затем всех женщин (отсортированных по возрасту). Это именно то, что вы должны видеть.
Если это не то, что вы видите, но это то, что вы хотите, вам нужно предоставить нам короткую, но полную программу, которая демонстрирует проблему. Расскажите нам, чего вы ожидали, и что вы на самом деле получили.
Если вы просто хотите упорядочить по нескольким критериям, проще всего просто использовать LINQ:
var ordered = people.OrderBy(p => p.Gender)
.ThenBy(p => p.Age)
.ToList();
РЕДАКТИРОВАТЬ: Демонстрация вашего кода (исправлены опечатки и для простоты используется анонимный тип), работающего:
using System;
using System.Collections.Generic;
using System.Linq;
class Test
{
static void Main()
{
var myClass = new[]
{
new { Type="first", Title="A" },
new { Type="second", Title="D" },
new { Type="first", Title="C" },
new { Type="second", Title="B" },
}.ToList();
var first = myClass.Where(x => x.Type == "first")
.ToList();
var second = myClass.Where(x => x.Type == "second")
.ToList();
first.Sort((x, y) => string.Compare(x.Title, y.Title));
second.Sort((x, y) => string.Compare(x.Title, y.Title));
myClass.Clear();
myClass.AddRange(first);
myClass.AddRange(second);
foreach (var x in myClass)
{
Console.WriteLine(x);
}
}
}
Вывод:
{ Type = first, Title = A }
{ Type = first, Title = C }
{ Type = second, Title = B }
{ Type = second, Title = D }
Комментарии:
1. @Джон Скит — Ну, это то, чего я хочу (я думаю). Я хочу, чтобы все мужчины (в этом случае они всегда были первыми) отсортировали их по возрасту. Итак, теперь у меня должны быть все мужчины по возрасту. Теперь я хочу всех женщин и упорядочиваю их по возрасту. Они также должны быть упорядочены по возрасту. Теперь я хочу объединить обе строки (сначала мужчин по возрасту, затем женщин по возрасту).
2. Очевидно, это не то, что он видит. Он хочет посмотреть, что ты говоришь в конце своего поста. Он хочет
A,C,B,D
и он получает что-то другое, кроме этого.3. @chobo2: Верно… было не совсем ясно, что вы получали в сравнении с тем, что вы хотели получить. Это то, что должно происходить, так что проблема, вероятно, в каком-то коде, который вы нам не показали. Пожалуйста, приведите короткий, но полный пример, который демонстрирует проблему.
4. @chobo2: Вы бы не поняли этого из опубликованного вами примера кода после исправления ошибок. Пожалуйста, приведите полный пример.
5. @chobo2: Я отредактировал свой ответ, чтобы дать короткую, но полную программу, которая демонстрирует работу кода. Запустите его для себя. Если вы сможете предложить аналогичную программу, которая действительно демонстрирует проблему, мы сможем это исправить.
Ответ №2:
Вы хотите, чтобы ваши объекты были отсортированы по типу, а затем по названию? Если да, LINQ приходит на помощь:
var sortedObjects = myClass.OrderBy(x => x.type).ThenBy(x => x.title);
Ответ №3:
Когда я делаю first.Sort() и second.Sort () все мои объекты расположены в правильном порядке на основе заголовка. Когда я очищаю и добавляю «первые» объекты в первый, а затем «второй» объект second, это разрушает мою сортировку.
Почему вы его очищаете? Это звучит ужасно похоже на следующее утверждение:
Когда я удаляю свои файлы, я больше не могу их открывать. Похоже, они отсутствуют на диске.
Комментарии:
1. Потому что я повторно вставляю их в правильном порядке, в котором я хочу их. Я беру все «первые» типы, затем все «вторые» типы упорядочивают все «первые типы», упорядочивают все «вторые» типы, а затем хотят поместить их обратно в исходный объект по порядку.
2. Да, но все, что вам нужно, это фильтр и сортировка по первому классу. Я хочу сказать, что вы не указываете ему прибегать, что вы должны сделать.
3. Я делаю это в 2 разных списках, потому что мне нужно извлечь разные типы, а затем отсортировать эти типы, а затем расположить типы по порядку. Я не уверен, как сделать все это в одном запросе. Я не понимаю, почему я должен указывать ему прибегать к нему, когда я помещаю в исходный список 2 отсортированных списка.
4. @chobo2 Потому что он не поддерживает их в отсортированном порядке, когда вы их перечитываете, afaik. Возможно, у вас проблемы из-за повторного использования исходного списка, но то, что вы делаете, должно дать вам то, что вы хотели.
Ответ №4:
Вы могли бы выполнить сортировку с помощью чего-то вроде этого:
// this is what you call to sort.
myClass.Sort(MyClass.NameComparison);
// This would sit in your class which you referenced as "MyClass"
public static NameComparison<MyClass> NameComparison
{
get
{
return delegate(MyClass c1, MyClass c2)
{
return c1.Name.CompareTo(c2.Name);
};
}
}
Комментарии:
1. Почему этот многострочный код должен быть проще, чем использование однострочного лямбда-выражения, которое он уже использует?
2. Это было бы полезно только в том случае, если бы у него не было доступного linq. Я все еще работаю над несколькими проектами с .net 2, и у меня нет преимуществ linq в этих проектах.
Ответ №5:
Это можно легко заменить на
myClass.OrderBy((m) => m.type).ThenBy((m) => m.title);
Это устраняет необходимость во втором списке и очистке и т.д.
Комментарии:
1. ну, это позволило бы сортировать типы по порядку в алфавитном порядке, но в моем реальном коде типы, которые идут первыми, а те, что идут вторыми, на самом деле не в алфавитном порядке. Это похоже на то, что документы Word идут первыми, документы Excel идут следующими, и, наконец, документы Powerpoint идут последними.
2. @chobo2: Похоже, что вы могли бы использовать метод для извлечения «приоритета» из типа документа (таким образом, Word вернет 1, Excel вернет 2, Powerpoint вернет 3). Тогда вы могли бы легко использовать LINQ.
Ответ №6:
Как насчет более объектно-ориентированного подхода? Просто реализуйте IComparable<MyClass> , тогда при вызове myList.Sort();
будет казаться, что список просто волшебным образом знает, как сортировать себя.
public class MyClass : IComparable<MyClass>
{
public string Type {get; set;}
public string Title {get; set;}
public int CompareTo(MyClass other)
{
if (other == null)
{
throw new ArgumentNullException("other");
}
else if(this.Type == other.Type)
{
return this.Title.CompareTo(other.Title);
}
else if(this.Type == "first")
{
return 1;
}
else
{
return -1;
}
// ...Or whatever you feel your sort needs to take into account.
}
}
Кроме того, это скрывает вашу отвратительно выглядящую логику сортировки от того, что вы действительно хотите сделать со списком; что является своего рода главной целью использования LINQ в первую очередь.