окно формы C # для сортировки списка номеров, который является строкой - PullRequest
2 голосов
/ 21 ноября 2011

Я взял проект у одного из наших разработчиков.

У нас есть оконная форма, которую мы используем для отправки строки, к которой у чата openfire есть доступ.

Некоторые номера названы "AAA ROOM 1" и "AAA ROOM 2" и т. Д. Если я использую этот код, он сортирует его по «AAA ROOM 1», «AAA ROOM 11», затем после «AAA ROOM 19» появляется «AAA ROOM 2»

RoomList.BeginUpdate();

foreach (Room r in Rooms) // original room list before getting it sorted
{
    RoomList.Items.Add(r.Name, IsMember(r.ID));
}

RoomList.EndUpdate();

Итак, я хотел отсортировать его в правильном порядке (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), поэтому я добавил код для сортировки списка комнат и его сортировать правильно,

foreach (Room r in Rooms)
{
    if (r.Name.Contains("AAA") && r.Name.Length <= 7)
                RoomList.Items.Add(r.Name, IsMember(r.ID));
}
foreach (Room r in Rooms)
{
    if (r.Name.Contains("AAA") && r.Name.Length > 7)
        RoomList.Items.Add(r.Name, IsMember(r.ID));
}
foreach (Room r in Rooms)
{
    if (!r.Name.Contains("AAA"))
        RoomList.Items.Add(r.Name, IsMember(r.ID));
}

Но когда я сохраняю данные, он использует этот код здесь, но он не обозначает нужную комнату. Это код, который он использует для сохранения членства (если я отмечу, чтобы добавить «AAA Room 11», то он фактически сохранит его как «AAA Room 18»).

MasterRecord.User.Memberships = "";
foreach (object o in RoomList.CheckedIndices)
{
    if (MasterRecord.User.Memberships.Length > 0)
        MasterRecord.User.Memberships += ",";

    MasterRecord.User.Memberships += GetItem(roomsui.StrToInt(o.ToString())).ToString();
}         

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

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

Ответы [ 3 ]

1 голос
/ 21 ноября 2011

По моему мнению, если рассматривать вопрос как длину, определяющую, какая комната сортируется первой, ошибочна. Если шаблон для названия комнаты - {ROOM-NAME}_{ROOM_NUMBER}, то трактуйте его так. (Как бы мне не хотелось это говорить, иногда: это может быть работа для регулярных выражений! )

var unordered = new[] { "CCC ROOM 10", "CCC ROOM 5", "AAA ROOM 1", "AAA ROOM 14", "AAA ROOM 2", "AAA ROOM 10", "AAA ROOM 5", "BBB ROOM 3", "BBB ROOM 12" };

Regex pattern = new Regex(@"^(\D+)(\d+)$");

var ordered = unordered
    .Select(
        r =>
        {
            Match match = pattern.Match(r);
            return new
            {
                Name = r,
                Prefix = match.Groups[1].Value,
                Number = Convert.ToInt32(match.Groups[2].Value)
            };
        }
    )
    .OrderBy(r => r.Prefix)
    .ThenBy(r => r.Number);

foreach (var room in ordered)
{
    Console.WriteLine(room.Name);
}

Этот код выдает следующий вывод ...

AAA ROOM 1
AAA ROOM 2
AAA ROOM 5
AAA ROOM 10
AAA ROOM 14
BBB ROOM 3
BBB ROOM 12
CCC ROOM 5
CCC ROOM 10

С помощью этого метода мы называем розу розой (или, в частности, строковое представление числа). Я использовал анонимный тип, чтобы мне не приходилось запускать матч дважды.

РЕДАКТИРОВАТЬ : Я заметил, что вы сказали Visual Studio 2008, поэтому вы можете не использовать .NET 4.0. Если нет, то многострочная лямбда может не работать (я точно не помню, когда это было добавлено). Вот еще один способ с использованием двух регулярных выражений и без анонимного типа. Я не уверен, что мне так больше не нравится, теперь, когда я это написал ...

var rooms = new[] { "CCC ROOM 10", "CCC ROOM 5", "AAA ROOM 1", "AAA ROOM 14", "AAA ROOM 2", "AAA ROOM 10", "AAA ROOM 5", "BBB ROOM 3", "BBB ROOM 12" };

Regex prefix = new Regex(@"^\D+");
Regex suffix = new Regex(@"\d+$");

var ordered2 = rooms
    .OrderBy(r => prefix.Match(r).Value)
    .ThenBy(r => Convert.ToInt32(suffix.Match(r).Value));

foreach (var room in ordered2)
{
    Console.WriteLine(room);
}

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

И, наконец, поскольку вы сказали, что вы новичок в разработке, я очень быстро коснусь регулярных выражений:

^\D+ = С самого начала строки найдите мне что-то, что не является цифрой один или несколько раз.

\d+$ = Найдите мне набор из одной или нескольких цифр, за которыми сразу следует конец строки.

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

0 голосов
/ 21 ноября 2011

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

попробуйте это быстрое решение для этого:

C # Буквенно-цифровая сортировка http://www.dotnetperls.com/alphanumeric-sorting

using System;
using System.Collections;

class Program
{
    static void Main()
    {
    string[] highways = new string[]
    {
        "100F",
        "50F",
        "SR100",
        "SR9"
    };
    //
    // We want to sort a string[] array called highways in an
    // alphanumeric way. Call the static Array.Sort method.
    //
    Array.Sort(highways, new AlphanumComparatorFast());
    //
    // Display the results
    //
    foreach (string h in highways)
    {
        Console.WriteLine(h);
    }
    }
}

использование вашей проблемы

var unordered = new[] { "CCC ROOM 10", "CCC ROOM 5", "AAA ROOM 1", "AAA ROOM 14", "AAA ROOM 2", "AAA ROOM 10", "AAA ROOM 5", "BBB ROOM 3", "BBB ROOM 12" };
var ordered = unordered.OrderBy(s => s, new AlphanumComparatorFast());

вот результат

AAA ROOM 1
AAA ROOM 2
AAA ROOM 5
AAA ROOM 10
AAA ROOM 14
BBB ROOM 3
BBB ROOM 12
CCC ROOM 5
CCC ROOM 10

вот хорошая статья о проблеме:

Сортировка для людей: Естественный порядок сортировки http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html

0 голосов
/ 21 ноября 2011

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

private int RoomWeight(Room r) {
    if (r.Name.Contains("AAA")) {
        if (r.Name.Length > 7) return 2;
        return 1;
    }
    return 3;
}

затем вы можете использовать для сортировки ваших комнат только одну строку: var sortedRooms = Rooms.OrderBy(x => RoomWeight(x)).ToList();

Следующим шагом будет анализ имени комнаты и вычисление значения RoomWeight в соответствии с вашими новыми требованиями

Наконец, вам нужно использовать отсортированный список комнат, чтобы заполнить список RoomList.Items, вы можете сделать это так же, как это было сделано:

 foreach (var r in sortedRooms) {
      RoomList.Items.Add(r.Name, IsMember(r.ID));
 }

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...