2009-07-01 2 views
3

У меня есть следующие элементы, отображаемые на странице asp.net (C#).Оптимизированный способ переопределения нумерации с помощью C#

1 Добро пожаловать
2 Что нового
2.1 Подарки
2.2 Идеи
2.3 Другие
2.3.1 Новизна
2.3.2 Лодки
2.4 Vehicals
2,5 Фрукты

Теперь пользователь может удалить любые дочерние элементы (не root для ex, пользователь может удалить подарки пункта 2.1 или новинку 2.3.1). Как только пользователь удалит ite m, мне нужно повторно создать структуру с помощью C#. Я ищу любые предложения/идеи/код для выполнения этой задачи.

1 Добро пожаловать
2 Что нового
2.1 Подарки (удаление)
2.2 Идеи
2.3 Другие
2.3.1 Новый (удалить)
2.3.2 лодки
2.4 Vehicals
2,5 Фрукты

Результат должен быть -

1 Добро пожаловать
2 Что нового
2.1 Идеи
2.2 Другие
2.2.1 Новый (удалить)
2.2.2 Лодки
2.3 Vehicals
2,4 Фрукты

+1

Как вы делаете определение, что должно быть 2,1 по сравнению, скажем, 3? – CAbbott

+0

2.1 является дочерним по 2, поэтому, если 2.1 удаляется, следующий ребенок 2.2 идеи становятся 2.1 – bugBurger

+2

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

ответ

2

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

List<Int32> numbering = new List<Int32>(); 

Int32 lastNestingLevel = -1; 

foreach (String line in lines) 
{ 
    String[] parts = line.Split(new Char[] { ' ' }, 2); 

    Int32 currentNestingLevel = parts[0].Count(c => c == '.'); 

    if (currentNestingLevel > lastNestingLevel) 
    { 
     // Start a new nesting level with number one. 
     numbering.Add(1); 
    } 
    else if (currentNestingLevel == lastNestingLevel) 
    { 
     // Increment the number of the current nesting level. 
     numbering[currentNestingLevel] += 1;  } 
    else if (currentNestingLevel < lastNestingLevel) 
    { 
     // Remove the deepest nesting level... 
     numbering.RemoveAt(numbering.Count - 1); 
     // ...and increment the numbering of the current nesting level. 
     numbering[currentNestingLevel] += 1; 
    } 

    lastNestingLevel = currentNestingLevel; 

    String newNumbering = String.Join(".", numbering 
     .Select(n => n.ToString()) 
     .ToArray()); 

    Console.WriteLine(newNumbering + " " + parts[1]); 
} 

Для следующего входа

List<String> lines = new List<String>() 
{ 
    "1 Welcome", 
    "2 Whats New", 
    //"2.1 Gifts", 
    "2.2 Ideas", 
    "2.3 Others", 
    //"2.3.1 Novelty", 
    "2.3.2 Boats", 
    "2.4 Vehicals", 
    "2.5 Fruits" 
}; 

выход состоит в следующем.

1 Welcome 
2 Whats New 
2.1 Ideas 
2.2 Others 
2.2.1 Boats 
2.3 Vehicals 
2.4 Fruits 

UPDATE

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

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

2.3.2.1 Vehicals 
2.5 Fruits <= nesting level drops by two 

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

+0

Большое спасибо Daniel.Very Очень красивая и простая логика, чтобы переупорядочить список предметов. Хотя спасибо всем за их предложения ..! – bugBurger

1

Я предлагаю использовать многомерный коллекции. Таким образом, когда вы удаляете первый элемент в коллекции «2» (2.1 - Подарки), «Идеи» автоматически станут новым первым элементом в этой коллекции, а затем будут считаны как 2.1 вместо 2.2

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

Возможно, я должен уточнить:
вы 'd имеет список «L1», который будет содержать элементы первого уровня.
Это будет выглядеть следующим образом:

List L1[2] 
    List Welcome[0] 
    List What's New[5] 
    List Gifts[0] 
    List Ideas[0] 
    List Others[2] 
     List Novelty[0] 
     List Boats[0] 
    List Vehicles[0] 
    List Fruits[0] 

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

Одним из самых простых способов достижения этой структуры является создание класса «Item», который содержит строку для ItemName, а также список дочерних элементов. Таким образом, у каждого предмета есть потенциал иметь детей или иметь детей.

5

Является ли число чисто «оптическим» сахаром для пользователя? Если да, я бы их на лету записывал во время записи вывода, не сохраняя ни одного номера.

+2

Это интересная идея. Это упрощает решение. – Giffyguy

+0

... и даже если вы хотите использовать ссылки или что угодно, вы также можете динамически создавать нумерацию, когда вам это нужно, связывая исходные элементы с номерами в словаре. А также позволяет легко использовать различные схемы нумерации, такие как буквы или римские номера. ;) – Lucero

+0

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

2

Еще одно предложение: если данные структурированы XML, вы можете использовать преобразование XSL, чтобы сделать нумерацию для вас ...

1

я придумал класс для хранения содержимого:

public class Content 
{ 
    public string Title { get; set; } 
    public IList<Content> SubContent 
    { 
     get; 
     private set; 
    } 

    private Content() 
    { 
    } 

    public Content(string title) 
    { 
     Title = title; 
     SubContent = new List<Content>(); 
    } 
} 

Тогда рекурсивная функция для числа/отображения содержимого:

private static void Display(string marker, IList<Content> content) 
    { 
     int count = 0; 
     foreach (Content c in content) 
     { 
      string label = marker + (marker.Length > 0 ? "." : "") + (++count); 
      Console.WriteLine(label + " " + c.Title); 
      if (c.SubContent.Count > 0) 
       Display(label, c.SubContent); 
     } 
    } 
Смежные вопросы