Not a very smart solution, but the following code renumbers a list of lines given as input. It splits each line at the space separating the numbering from the rest, determines the nesting level by counting the number of dots in the numbering, and uses this information together with the nesting level of the last line to update a list with the current numbering for each nesting level. Finally the current numbering stored in the list is joined with the text and outputed.
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]);
}
For the following input
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"
};
the output is the following.
1 Welcome
2 Whats New
2.1 Ideas
2.2 Others
2.2.1 Boats
2.3 Vehicals
2.4 Fruits
UPDATE
Here is a variant using a dictionary - it simplifies the update, but complicates the generation of the new numbering a bit.
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]);
}
This variant also fixes a bug in the first version. If the nesting level drops by more than one at once, the first variant will produce false outputs.
2.3.2.1 Vehicals
2.5 Fruits <= nesting level drops by two
I assume an input where the nesting level raises by more than one at once is not valid or at least a more precise definition how to handle this case is required, but both variants may have problems with that kind of inputs.