Description
A different approach into handling strings. This case is usefull when you want to alter parts of a string depending on char types. For example numbers in a string.
The principle is simple. Iterate through the string and sepparate components into 2 lists. Class PartialStringIndex will store the partial string and the index (which is priority to recompose)
Goal
For example given the expression “abc123def456” you can sepparate the string by rule char is number, the class will provide 2 lists: {“abc”, “def”} and {“123”, “456”}.
Usage is:
Regex regex = new Regex("[0-9]"); StringDestructure sd = StringDestructure.By("abc123def456", (ch) => regex.Match(ch.ToString()).Success); sd.OnConditionMet((str) => str); sd.OnConditionNotMet((str) => str.ToUpper()); string result = sd.Recompose(); ///THE RESULT WILL BE "ABC123DEF456"
Implementation
public class StringDestructure { private class PartialStringIndex { public string Context; public int Index; } //Collection of sepparated elements List ElementsMeetCondition; List ElementsDoNotMeetCondition; //altering actions on each of them List<Func<string, string>> ActionsOnConditionMet; List<Func<string, string>> ActionsOnConditionNotMet; private StringDestructure(string Context, Predicate predicate) { ElementsMeetCondition = new List(); ElementsDoNotMeetCondition = new List(); ActionsOnConditionMet = new List<Func<string, string>>(); ActionsOnConditionNotMet = new List<Func<string, string>>(); StringBuilder temporary = new StringBuilder(); bool storeToCondition = false; int recomposeIndex = 0; for(int i = 0; i < Context.Length;i++) { char ch = Context[i]; if (i == 0) { if (predicate(ch)) { temporary.Append(ch); storeToCondition = true; } else { temporary.Append(ch); storeToCondition = false; } } else { if (predicate(ch)) { if (storeToCondition) { temporary.Append(ch); } else { ElementsDoNotMeetCondition.Add(new PartialStringIndex { Context = temporary.ToString(), Index = recomposeIndex }); recomposeIndex++; temporary.Clear(); temporary.Append(ch); } storeToCondition = true; } else//if (!predicate(ch) { if (storeToCondition) { ElementsMeetCondition.Add(new PartialStringIndex { Context = temporary.ToString(), Index = recomposeIndex }); recomposeIndex++; temporary.Clear(); temporary.Append(ch); } else { temporary.Append(ch); } storeToCondition = false; } } if (i == Context.Length - 1) { if (storeToCondition) ElementsMeetCondition.Add(new PartialStringIndex { Context = temporary.ToString(), Index = recomposeIndex }); else ElementsDoNotMeetCondition.Add(new PartialStringIndex { Context = temporary.ToString(), Index = recomposeIndex }); } } } //Initializer public static StringDestructure By(string Context, Predicate ListSplitCondition) { return new StringDestructure(Context, ListSplitCondition); } //Add am altering action for partial strings that meet condition public StringDestructure OnConditionMet(Func<string, string> func) { this.ActionsOnConditionMet.Add(func); return this; } //Add am altering action for partial strings that do not meet condition public StringDestructure OnConditionNotMet(Func<string, string> func) { this.ActionsOnConditionNotMet.Add(func); return this; } public string Recompose() { foreach(var item in this.ElementsMeetCondition) { string partialString = item.Context; foreach (var action in this.ActionsOnConditionMet) { partialString = action(partialString); } item.Context = partialString; } foreach (var item in this.ElementsDoNotMeetCondition) { string partialString = item.Context; foreach (var action in this.ActionsOnConditionNotMet) { partialString = action(partialString); } item.Context = partialString; } List allitems = this.ElementsMeetCondition.Concat(this.ElementsDoNotMeetCondition).ToList(); Comparison comparison = (first, second) => { return first.Index.CompareTo(second.Index); }; allitems.Sort(comparison); return string.Concat(allitems.Select(x => x.Context)); } }