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
Generate
method implementation: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 used
NTree
class implementation:// 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
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
Another more complex test case: 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.
foreach
inside theGenerate
method seems really suspicious. Are you sure you need all of them? As I can see you have a recursiveTraverse
method which is unused. Do you use it in a different code piece which is not shared with us? \$\endgroup\$