Настройка порядка сортировки массивов C # - PullRequest
1 голос
/ 24 июня 2009

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

Я пишу и клиент IRC и пытаюсь отсортировать список имен пользователей (который должен быть отсортирован по уровню доступа пользователей в текущем канале).

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

Уровень доступа каждого пользователя обозначается одним символом в начале каждого имени пользователя. Эти символы зарезервированы, поэтому нет потенциальной проблемы с именем, начинающимся с одного из символов. Символы от высшего к низшему (в порядке их сортировки): ~ & @ % +

Пользователи без какого-либо доступа не имеют символа перед своим именем пользователя. Они должны быть внизу списка.

Например: несортированный массив может содержать следующее: ~ user1 ~ user84 @ user3 & user8 + user39 user002 user2838% user29

И нужно отсортировать так, чтобы элементы были в следующем порядке: ~ user1 ~ user84 & user8 @ user3% user29 + user39 user002 user2838

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

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

Ответы [ 5 ]

1 голос
/ 24 июня 2009

Вы можете использовать SortedList<K,V> с K (ключом), реализующим интерфейс IComparable, который затем определяет критерии вашего вида. V может просто быть нулевым или одним и тем же объектом K.

1 голос
/ 24 июня 2009

Вы можете дать IComparer<T> или Comparison<T> до Array.Sort. Тогда вам просто нужно осуществить сравнение самостоятельно. Если это сравнительно сложное сравнение (которое звучит так), я бы реализовал IComparer<T> в отдельном классе, который вы можете легко протестировать. Затем позвоните:

Array.Sort(userNames, new UserNameComparer());

Возможно, вы захотите определить удобный экземпляр, если у UserNameComparer нет состояния:

Array.Sort(userNames, UserNameComparer.Instance);

List<T> имеет аналогичные параметры для сортировки - я бы лично использовал список, а не массив, если вы собираетесь регулярно добавлять / удалять элементы.

На самом деле, звучит так, как будто вам не нужно выполнять полную сортировку. Удаление пользователя не меняет порядок сортировки, а вставка означает только вставку в нужную точку. Другими словами, вам нужно:

  • Создать список и отсортировать его, чтобы начать с
  • Удаление пользователя - простая операция
  • Добавление пользователя требует выяснения, куда его вставить

Вы можете сделать последний шаг, используя Array.BinarySearch или List.BinarySearch, что снова позволит вам указать пользовательский IComparer<T>. Как только вы знаете, куда вставить пользователя, вы можете сделать это относительно дешево (по сравнению с повторной сортировкой всей коллекции).

1 голос
/ 24 июня 2009

Пока массив содержит объект, реализуйте IComparable для объекта и затем вызовите Array.Sort ().

То есть, если коллекция изменчива, я бы рекомендовал использовать список <>.

0 голосов
/ 24 июня 2009

Я сделал попытку сортировки и предложил следующий подход:

List<char> levelChars = new List<char>();
levelChars.AddRange("+%@&~".ToCharArray());
List<string> names = new List<string>();
names.AddRange(new[]{"~user1", "~user84",  "@user3", "&user8", "+user39", "user002", "user2838", "%user29"});
names.Sort((x,y) =>
               {
                   int xLevel = levelChars.IndexOf(x[0]);
                   int yLevel = levelChars.IndexOf(y[0]);

                   if (xLevel != yLevel)
                   {
                       // if xLevel is higher; x should come before y
                       return xLevel > yLevel ? -1 : 1;
                   }

                   // x and y have the same level; regular string comparison
                   // will do the job
                   return x.CompareTo(y);                       
               });

Этот код сравнения может также существовать в методе Compare реализации IComparer<T>.

0 голосов
/ 24 июня 2009

Вам следует взглянуть на интерфейс IComparer (или это универсальная версия ). При реализации метода CompareTo проверьте, содержит ли одно из двух имен пользователей один из ваших зарезервированных символов. Если ни один из них не имеет специального зарезервированного символа или оба имеют одинаковый символ, вызовите метод String.CompareTo, который будет обрабатывать сортировку по алфавиту. В противном случае используйте вашу собственную логику сортировки.

...