There is a String.Replace method in C# and it is 1-1 mapping replacing operation, i.e. single Unicode character / string source replaced with another single Unicode character / string target. Considering the case of 1-to-multiple replacing task, for example, replacing "1" in "123" with "A", "B" and "C" separately (result: "A23", "B23" and "C23"), I am attempting to propose a Generate method to deal with this kind of task.
Replacing Rule Representation
Tree structure is used for representing 1-to-multiple replacing rule. Following the mentioned example, the tree structure is like:
(root)-- "1" ---- "A"
|---- "B"
|---- "C"
The nodes in level 2 are the old strings to be replaced and the the nodes in level 3 are the new strings to replace all occurrences of its parent node.
The experimental implementation
The Generate method
public static class StringsBatchReplacingTool
{
public static List<string> Generate(string inputString, NTree<string> replacingRules)
{
List<string> results = new List<string>();
results.Add(inputString);
foreach (var Node in replacingRules.Nodes) // First layer
{
if (!inputString.Contains(Node.Data))
{
continue;
}
results = BatchReplace(results, Node);
}
return results;
}
private static List<string> BatchReplace(List<string> input, NTree<string> replacingRules)
{
List<string> results = new List<string>();
foreach (var replaceTarget in replacingRules.Nodes)
{
foreach (var inputItem in input)
{
results.Add(inputItem.Replace(replacingRules.Data, replaceTarget.Data));
}
}
return results;
}
}
The NTree class
// Reference: https://stackoverflow.com/a/2012855
public delegate void TreeVisitor<T>(T nodeData);
public class NTree<T>
{
public T Data;
public LinkedList<NTree<T>> Nodes;
public NTree()
{
Nodes = new LinkedList<NTree<T>>();
}
public NTree(T data)
{
this.Data = data;
Nodes = new LinkedList<NTree<T>>();
}
public void AddChild(T data)
{
Nodes.AddFirst(new NTree<T>(data));
}
public void AddChild(IEnumerable<T> data)
{
foreach (var eachData in data)
{
AddChild(eachData);
}
}
/// <summary>
/// Get the specific child with the given index.
/// </summary>
/// <param name="i">Index of child, start from 0</param>
/// <returns></returns>
public NTree<T> GetChild(int i)
{
i++;
foreach (NTree<T> n in Nodes)
if (--i == 0)
return n;
return null;
}
public void Traverse(NTree<T> node, TreeVisitor<T> visitor)
{
visitor(node.Data);
foreach (NTree<T> kid in node.Nodes)
Traverse(kid, visitor);
}
Test Cases
Simple
Following the mentioned example, the code for testing:
NTree<string> nTree = new NTree<string>();
nTree.AddChild("1");
nTree.GetChild(0).AddChild("C");
nTree.GetChild(0).AddChild("B");
nTree.GetChild(0).AddChild("A");
var testResults = StringsBatchReplacingTool.Generate("123", nTree);
foreach (var eachResult in testResults)
{
Console.WriteLine(eachResult);
}
The output of above code:
A23
B23
C23
Complex
For input string "123", replacing "1" with "A", "B" and "C" and replacing "2" with "D", "E" and "F" separately.
NTree<string> nTree = new NTree<string>();
nTree.AddChild("1");
nTree.GetChild(0).AddChild("C");
nTree.GetChild(0).AddChild("B");
nTree.GetChild(0).AddChild("A");
nTree.AddChild("2");
nTree.GetChild(0).AddChild("F");
nTree.GetChild(0).AddChild("E");
nTree.GetChild(0).AddChild("D");
var testResults = StringsBatchReplacingTool.Generate("123", nTree);
foreach (var eachResult in testResults)
{
Console.WriteLine(eachResult);
}
The output of above code:
AD3
AE3
AF3
BD3
BE3
BF3
CD3
CE3
CF3
All suggestions are welcome.
foreachinside theGeneratemethod seems really suspicious. Are you sure you need all of them? As I can see you have a recursiveTraversemethod which is unused. Do you use it in a different code piece which is not shared with us? \$\endgroup\$Traversewill likely blow up at run time. It does not have the "recursive pattern". First - test for base case - return if base case. Second - reduce one step closer to the base case. Third - recursive call. Fourth - return with the Third step results. \$\endgroup\$Generate("1231", nTree)orGenerate("222", nTree)\$\endgroup\$The nodes in level 2 are the old strings...I'm surmising that the "old string" is not the whole string but an individual character in the string. Yes? \$\endgroup\$StringsBatchReplacingToolshould either be aTreeVisitoror use aTreeVisitor. Either theNTree<T>class should not be generic and not have a "visitor", OR this code is incomplete not ready for review and therefore be closed. \$\endgroup\$