使用C#重新排序编号的优化方法

时间:2009-07-01 17:10:45

标签: c# algorithm

我在asp.net页面(C#)上显示以下项目。

1欢迎光临 2什么是新的 2.1礼物
2.2想法
2.3其他
2.3.1新颖性 2.3.2船只
2.4车辆
2.5水果

现在用户可以删除任何子项(不是root用户可以删除项目2.1礼物或项目2.3.1新颖性)一旦用户删除该项目,我需要使用C#重新编号结构。我正在寻找任何建议/想法/代码来完成这项任务。

1欢迎光临 2什么是新的 2.1礼物(删除)
2.2想法
2.3其他
2.3.1新颖性(删除)
2.3.2船只
2.4车辆
2.5水果

结果应为 -

1欢迎光临 2什么是新的 2.1想法
2.2其他
2.2.1新颖性(删除)
2.2.2船只
2.3车辆
2.4水果

5 个答案:

答案 0 :(得分:5)

这个号码纯粹是用户的“光学”糖吗?如果是的话,我会在编写输出时动态编号,而不会将数字保存在任何地方。

答案 1 :(得分:2)

不是一个非常智能的解决方案,但以下代码重新编号作为输入给出的行列表。它将每行分开编号与其余编号分隔,通过计算编号中的点数来确定嵌套级别,并将此信息与最后一行的嵌套级别一起使用,以使用当前编号更新列表每个筑巢级别。最后,存储在列表中的当前编号将与文本连接并输出。

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

<强>更新

这是使用字典的变体 - 它简化了更新,但稍微复制了新编号的生成。

Dictionary<Int32, Int32> numbering = new Dictionary<Int32, 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)
    {
        numbering[currentNestingLevel] = 1;
    }
    else
    {
        numbering[currentNestingLevel] += 1;
    }

    lastNestingLevel = currentNestingLevel;

    String newNumbering = String.Join(".", numbering
        .Where(n => n.Key <= currentNestingLevel)
        .OrderBy(n => n.Key)
        .Select(n => n.Value.ToString())
        .ToArray());

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

此变体还修复了第一个版本中的错误。如果嵌套级别一次下降超过一个,则第一个变量将产生错误输出。

2.3.2.1 Vehicals
2.5 Fruits <= nesting level drops by two

我假设一个输入,其中嵌套级别一次提升多于一个是无效的,或者至少需要更精确的定义如何处理这种情况,但这两种变体可能都有这种输入的问题。

答案 2 :(得分:2)

另一个建议:如果数据是结构化XML,您可以使用XSL转换为您编号......

答案 3 :(得分:1)

我建议使用多维集合。因此,当您删除“2”集合中的第一个项目(2.1 - Gifts)时,“Ideas”将自动成为该集合中的新第一个项目,从那时起将被视为2.1而不是2.2

但由于“1”系列中只有一个项目,因此不会列为1.1 这是你必须要注意的事情......

也许我应该详细说明:
你有一个列表“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的String以及子项列表。这样每件物品都有可能生孩子,或者没有孩子。

答案 4 :(得分: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);
        }
    }