Use more than one character to replace other - c#

I have a app and in this app it is possible with a function to replace some characters in a word with a other character
var newCharacter = "H";
if (/*something happens here and than the currentCharacter will be replaced*/)
{
// Replace the currentCharacter in the word with a random newCharacter.
wordString = wordString.Replace(currentCharacter, newCharacter);
}
now all the characters will be replaced with the code above with the "H". But i want more letters so by example the H, E, A, S
what is the best way to do this?
When i do this:
var newCharacter = "H" + "L" + "S";
it replaced the currentCharacter with H AND L AND S but i just want it to replace with H OR L OR S not all three
so if you have a word with HELLO and you want to replace the O with the newCharacter my output now is HELLHLS
O -> HLS
but O needs to be -> H or L or S

Here is a way to do using LINQ.You can add the characters you want to remove in the array excpChar
char[] excpChar= new[] { 'O','N' };
string word = "LONDON";
var result = excpChar.Select(ch => word = word.Replace(ch.ToString(), ""));
Console.WriteLine(result.Last());

The Replace function replaces all the occurences at once, this is not what we want. Let's do a ReplaceFirst function, only replacing the first occurence (one could make an extension method out of this):
static string ReplaceFirst(string word, char find, char replacement)
{
int location = word.IndexOf(find);
if (location > -1)
return word.Substring(0, location) + replacement + word.Substring(location + 1);
else
return word;
}
Then we can use a random generator to replace the target letter with different letters through successive calls of ReplaceFirst:
string word = "TpqsdfTsqfdTomTmeT";
char find = 'T';
char[] replacements = { 'H', 'E', 'A', 'S' };
Random random = new Random();
while (word.Contains(find))
word = ReplaceFirst(word, find, replacements[random.Next(replacements.Length)]);
word now may be EpqsdfSsqfdEomHmeS or SpqsdfSsqfdHomHmeE or ...

You can do like following :
string test = "abcde";
var result = ChangeFor(test, new char[] {'b', 'c'}, 'z');
// result = "azzde"
with ChangeFor :
private string ChangeFor(string input, IEnumerable<char> before, char after)
{
string result = input;
foreach (char c in before)
{
result = result.Replace(c, after);
}
return result;
}

Related

Check Multiple Contains() and store the value dynamically

I have a string function in which i have to check multiple characters. My code is
if(str.Contains("R") || str.Contains("f") || str.Contains("W") )
{
string letter= "";
}
My question is if string contains R then it has to be stored in letter variable, if f contains it has to be stored. How can I achieve it by not using multiple if conditions??
You could use string.IndexOfAny to find the position of one of the letters
int pos = str.IndexOfAny(new char[] {'R','f','W'});
if(pos >= 0)
{
string letter = str[pos].ToString();
....
}
Perhaps you want something like this?
string str = "abcRefg";
var letters = new[] { "R", "f", "W" };
string foundLetter = null;
foreach (var letter in letters)
{
if (str.Contains(letter))
{
foundLetter = letter;
break;
}
}
Since you need to know which characters str contains, you can use the Enumerable.Intersect extension method.
char[] characters = {'R', 'f', 'W'};
var common = str.Intersect(characters).ToList();
foreach(char c in common)
{
}

How can I capitalize every third letter of a string in C#?

How can I capitalize every third letter of a string in C#?
I loop through the whole string with a for loop, but I can't think of the sequence right now.
I suspect you just want something like this:
// String is immutable; copy to a char[] so we can modify that in-place
char[] chars = input.ToCharArray();
for (int i = 0; i < chars.Length; i += 3)
{
chars[i] = char.ToUpper(chars[i]);
}
// Now construct a new String from the modified character array
string output = new string(chars);
That assumes you want to start capitalizing from the first letter, so "abcdefghij" would become "AbcDefGhiJ". If you want to start capitalizing elsewhere, just change the initial value of i.
var s = "Lorem ipsum";
var foo = new string(s
.Select((c, i) => (i + 1) % 3 == 0 ? Char.ToUpper(c) : c)
.ToArray());
You are already looping through the characters inside a string? Then add a counter, increment it on each iteration, and if it is 3, then use .ToUpper(currentCharacter) to make it upper case. Then reset your counter.
You could just use a regular expression.
If the answer is every third char then you want
var input = "sdkgjslgjsklvaswlet";
var regex = new Regex("(..)(.)");
var replacement = regex.Replace(input, delegate(Match m)
{
return m.Groups[1].Value + m.Groups[2].Value.ToUpper();
});
If you want every third character, but starting with the first you want:
var input = "sdkgjslgjsklvaswlet";
var regex = new Regex("(.)(..)");
var replacement = regex.Replace(input, delegate(Match m)
{
return m.Groups[1].Value.ToUpper() + m.Groups[2].Value;
});
If you want a loop, you can convert to a character array first, so you can alter the values.
For every third character:
var x = input.ToCharArray();
for (var i = 2; i <x.Length; i+=3) {
x[i] = char.ToUpper(x[i]);
}
var replacement = new string(x);
For every third character from the beginning:
var x = input.ToCharArray();
for (var i = 0; i <x.Length; i+=3) {
x[i] = char.ToUpper(x[i]);
}
var replacement = new string(x);

How can I convert text to Pascal case?

I have a variable name, say "WARD_VS_VITAL_SIGNS", and I want to convert it to Pascal case format: "WardVsVitalSigns"
WARD_VS_VITAL_SIGNS -> WardVsVitalSigns
How can I make this conversion?
You do not need a regular expression for that.
var yourString = "WARD_VS_VITAL_SIGNS".ToLower().Replace("_", " ");
TextInfo info = CultureInfo.CurrentCulture.TextInfo;
yourString = info.ToTitleCase(yourString).Replace(" ", string.Empty);
Console.WriteLine(yourString);
Here is my quick LINQ & regex solution to save someone's time:
using System;
using System.Linq;
using System.Text.RegularExpressions;
public string ToPascalCase(string original)
{
Regex invalidCharsRgx = new Regex("[^_a-zA-Z0-9]");
Regex whiteSpace = new Regex(#"(?<=\s)");
Regex startsWithLowerCaseChar = new Regex("^[a-z]");
Regex firstCharFollowedByUpperCasesOnly = new Regex("(?<=[A-Z])[A-Z0-9]+$");
Regex lowerCaseNextToNumber = new Regex("(?<=[0-9])[a-z]");
Regex upperCaseInside = new Regex("(?<=[A-Z])[A-Z]+?((?=[A-Z][a-z])|(?=[0-9]))");
// replace white spaces with undescore, then replace all invalid chars with empty string
var pascalCase = invalidCharsRgx.Replace(whiteSpace.Replace(original, "_"), string.Empty)
// split by underscores
.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)
// set first letter to uppercase
.Select(w => startsWithLowerCaseChar.Replace(w, m => m.Value.ToUpper()))
// replace second and all following upper case letters to lower if there is no next lower (ABC -> Abc)
.Select(w => firstCharFollowedByUpperCasesOnly.Replace(w, m => m.Value.ToLower()))
// set upper case the first lower case following a number (Ab9cd -> Ab9Cd)
.Select(w => lowerCaseNextToNumber.Replace(w, m => m.Value.ToUpper()))
// lower second and next upper case letters except the last if it follows by any lower (ABcDEf -> AbcDef)
.Select(w => upperCaseInside.Replace(w, m => m.Value.ToLower()));
return string.Concat(pascalCase);
}
Example output:
"WARD_VS_VITAL_SIGNS" "WardVsVitalSigns"
"Who am I?" "WhoAmI"
"I ate before you got here" "IAteBeforeYouGotHere"
"Hello|Who|Am|I?" "HelloWhoAmI"
"Live long and prosper" "LiveLongAndProsper"
"Lorem ipsum dolor..." "LoremIpsumDolor"
"CoolSP" "CoolSp"
"AB9CD" "Ab9Cd"
"CCCTrigger" "CccTrigger"
"CIRC" "Circ"
"ID_SOME" "IdSome"
"ID_SomeOther" "IdSomeOther"
"ID_SOMEOther" "IdSomeOther"
"CCC_SOME_2Phases" "CccSome2Phases"
"AlreadyGoodPascalCase" "AlreadyGoodPascalCase"
"999 999 99 9 " "999999999"
"1 2 3 " "123"
"1 AB cd EFDDD 8" "1AbCdEfddd8"
"INVALID VALUE AND _2THINGS" "InvalidValueAnd2Things"
First off, you are asking for title case and not camel-case, because in camel-case the first letter of the word is lowercase and your example shows you want the first letter to be uppercase.
At any rate, here is how you could achieve your desired result:
string textToChange = "WARD_VS_VITAL_SIGNS";
System.Text.StringBuilder resultBuilder = new System.Text.StringBuilder();
foreach(char c in textToChange)
{
// Replace anything, but letters and digits, with space
if(!Char.IsLetterOrDigit(c))
{
resultBuilder.Append(" ");
}
else
{
resultBuilder.Append(c);
}
}
string result = resultBuilder.ToString();
// Make result string all lowercase, because ToTitleCase does not change all uppercase correctly
result = result.ToLower();
// Creates a TextInfo based on the "en-US" culture.
TextInfo myTI = new CultureInfo("en-US",false).TextInfo;
result = myTI.ToTitleCase(result).Replace(" ", String.Empty);
Note: result is now WardVsVitalSigns.
If you did, in fact, want camel-case, then after all of the above, just use this helper function:
public string LowercaseFirst(string s)
{
if (string.IsNullOrEmpty(s))
{
return string.Empty;
}
char[] a = s.ToCharArray();
a[0] = char.ToLower(a[0]);
return new string(a);
}
So you could call it, like this:
result = LowercaseFirst(result);
Single semicolon solution:
public static string PascalCase(this string word)
{
return string.Join("" , word.Split('_')
.Select(w => w.Trim())
.Where(w => w.Length > 0)
.Select(w => w.Substring(0,1).ToUpper() + w.Substring(1).ToLower()));
}
Extension method for System.String with .NET Core compatible code by using System and System.Linq.
Does not modify the original string.
.NET Fiddle for the code below
using System;
using System.Linq;
public static class StringExtensions
{
/// <summary>
/// Converts a string to PascalCase
/// </summary>
/// <param name="str">String to convert</param>
public static string ToPascalCase(this string str){
// Replace all non-letter and non-digits with an underscore and lowercase the rest.
string sample = string.Join("", str?.Select(c => Char.IsLetterOrDigit(c) ? c.ToString().ToLower() : "_").ToArray());
// Split the resulting string by underscore
// Select first character, uppercase it and concatenate with the rest of the string
var arr = sample?
.Split(new []{'_'}, StringSplitOptions.RemoveEmptyEntries)
.Select(s => $"{s.Substring(0, 1).ToUpper()}{s.Substring(1)}");
// Join the resulting collection
sample = string.Join("", arr);
return sample;
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("WARD_VS_VITAL_SIGNS".ToPascalCase()); // WardVsVitalSigns
Console.WriteLine("Who am I?".ToPascalCase()); // WhoAmI
Console.WriteLine("I ate before you got here".ToPascalCase()); // IAteBeforeYouGotHere
Console.WriteLine("Hello|Who|Am|I?".ToPascalCase()); // HelloWhoAmI
Console.WriteLine("Live long and prosper".ToPascalCase()); // LiveLongAndProsper
Console.WriteLine("Lorem ipsum dolor sit amet, consectetur adipiscing elit.".ToPascalCase()); // LoremIpsumDolorSitAmetConsecteturAdipiscingElit
}
}
var xs = "WARD_VS_VITAL_SIGNS".Split('_');
var q =
from x in xs
let first_char = char.ToUpper(x[0])
let rest_chars = new string(x.Skip(1).Select(c => char.ToLower(c)).ToArray())
select first_char + rest_chars;
Some answers are correct but I really don't understand why they set the text to LowerCase first, because the ToTitleCase will handle that automatically:
var text = "WARD_VS_VITAL_SIGNS".Replace("_", " ");
TextInfo textInfo = CultureInfo.CurrentCulture.TextInfo;
text = textInfo.ToTitleCase(text).Replace(" ", string.Empty);
Console.WriteLine(text);
You can use this:
public static string ConvertToPascal(string underScoreString)
{
string[] words = underScoreString.Split('_');
StringBuilder returnStr = new StringBuilder();
foreach (string wrd in words)
{
returnStr.Append(wrd.Substring(0, 1).ToUpper());
returnStr.Append(wrd.Substring(1).ToLower());
}
return returnStr.ToString();
}
This answer understands that there are Unicode categories which can be tapped while processing the text to ignore the connecting characters such as - or _. In regex parlance it is \p (for category) then the type which is {Pc} for punctuation and connector type character; \p{Pc} using our MatchEvaluator which is kicked off for each match within a session.
So during the match phase, we get words and ignore the punctuations, so the replace operation handles the removal of the connector character. Once we have the match word, we can push it down to lowercase and then only up case the first character as the return for the replace:
public static class StringExtensions
{
public static string ToPascalCase(this string initial)
=> Regex.Replace(initial,
// (Match any non punctuation) & then ignore any punctuation
#"([^\p{Pc}]+)[\p{Pc}]*",
new MatchEvaluator(mtch =>
{
var word = mtch.Groups[1].Value.ToLower();
return $"{Char.ToUpper(word[0])}{word.Substring(1)}";
}));
}
Usage:
"TOO_MUCH_BABY".ToPascalCase(); // TooMuchBaby
"HELLO|ITS|ME".ToPascalCase(); // HelloItsMe
See Word Character in Character Classes in Regular Expressions
Pc Punctuation, Connector. This category includes ten characters, the
most commonly used of which is the LOWLINE character (_), u+005F.
If you did want to replace any formatted string into a pascal case then you can do
public static string ToPascalCase(this string original)
{
string newString = string.Empty;
bool makeNextCharacterUpper = false;
for (int index = 0; index < original.Length; index++)
{
char c = original[index];
if(index == 0)
newString += $"{char.ToUpper(c)}";
else if (makeNextCharacterUpper)
{
newString += $"{char.ToUpper(c)}";
makeNextCharacterUpper = false;
}
else if (char.IsUpper(c))
newString += $" {c}";
else if (char.IsLower(c) || char.IsNumber(c))
newString += c;
else if (char.IsNumber(c))
newString += $"{c}";
else
{
makeNextCharacterUpper = true;
newString += ' ';
}
}
return newString.TrimStart().Replace(" ", "");
}
Tested with strings
I|Can|Get|A|String
ICan_GetAString
i-can-get-a-string
i_can_get_a_string
I Can Get A String
ICanGetAString
I found this gist useful after adding a ToLower() to it.
"WARD_VS_VITAL_SIGNS"
.ToLower()
.Split(new [] {"_"}, StringSplitOptions.RemoveEmptyEntries)
.Select(s => char.ToUpperInvariant(s[0]) + s.Substring(1, s.Length - 1))
.Aggregate(string.Empty, (s1, s2) => s1 + s2)

How to replace exclusively?

Okay, I have a pretty obvious but apparently nontrivial problem to solve.
Suppose I have a simple string ab.
Now I want to replace a with b and b with a, so I end up with ba.
The hand on solution would be to do the two replaces consecutively. But the result from that is either aa or bb depending on the order.
Obviously, the production situation will have to deal with much more complex strings and more replacements than two, but the problem still applies.
One idea I had was to save positions where I replaced something. But that threw me off as soon as the replacement had a different length than the original needle.
This is general problem, but I'm working with C#. Here's some code I came up with:
string original = "abc";
Regex[] expressions = new Regex[]
{
new Regex("a"), //replaced by ab
new Regex("b") //replaced by c
};
string[] replacements = new string[]
{
"ab",
"c"
};
for (int i = 0; i < expressions.Length; i++)
original = expressions[i].Replace(original, replacements[i]);
//Expected result: abcc
//Actual result: accc <- the b is replaced by c in the second pass.
So is there a simple way to solve this?
If you are talking about simple one-to-one conversions, converting to a char array and doing a switch is probably ideal, however you seem to be looking for more complex replacements.
Basically the trick is to create an intermediate character to mark your temporaries. Rather than showing the actual code, here is what the string would look like as it was transformed:
ab
%1b
%1%2
b%2
ba
So basically, replace % with %%, then the first match with %1 and so on. Once they are all done replace %1 with its output and so on, finally replacing %% with %.
Be careful though, if you can guarantee that your intermediate syntax doesn't taint your input you are okay, if you cannot, you will need to use a tricks to make sure you aren't prefaced by an odd number of %. (So %%a would match, but %%%a would not, since that would mean the special value %a)
Here’s one solution. Try all the regular expressions against the string, do the replacement on the earliest match, then recurse on the remaining part of the string. If you need this to be faster but more complicated, you could ask for all Matches() right at the start and process them from left to right, adjusting their Indexes as you replace expressions with longer and shorter strings, and throwing away any overlaps.
using System;
using System.IO;
using System.Text.RegularExpressions;
class MultiRegex {
static String Replace(String text, Regex[] expressions,
String[] replacements, int start=0)
{
// Try matching each regex; save the first match
Match firstMatch = null;
int firstMatchingExpressionIndex = -1;
for (int i = 0; i < expressions.Length; i++) {
Regex r = expressions[i];
Match m = r.Match(text, start);
if (m.Success
&& (firstMatch == null || m.Index < firstMatch.Index))
{
firstMatch = m;
firstMatchingExpressionIndex = i;
}
}
if (firstMatch == null) {
/* No matches anywhere */
return text;
}
// Replace text, then recurse
String newText = text.Substring(0, firstMatch.Index)
+ replacements[firstMatchingExpressionIndex]
+ text.Substring(firstMatch.Index + firstMatch.Length);
return Replace(newText, expressions, replacements,
start + replacements[firstMatchingExpressionIndex].Length);
}
public static void Main() {
Regex[] expressions = new Regex[]
{
new Regex("a"), //replaced by ab
new Regex("b") //replaced by c
};
string[] replacements = new string[]
{
"ab",
"c"
};
string original = "a b c";
Console.WriteLine(
Replace(original, expressions, replacements));
// Should be "baz foo bar"
Console.WriteLine(Replace("foo bar baz",
new Regex[] { new Regex("bar"), new Regex("baz"),
new Regex("foo") },
new String[] { "foo", "bar", "baz" }));
}
}
This prints:
ab c c
baz foo bar
If you use (\ba\b) to represent matching the letter a and only the letter a, whereas ab won't be matched. Similar for the b, it would be (\bb\b).
string original = "a b c";
Regex[] expressions = new Regex[] {
// # sign used to signify a literal string
new Regex(#"(\ba\b)"), // \b represents a word boundary, between a word and a space
new Regex(#"(\bb\b)"),
};
string[] replacements = new string[] {
"ab",
"c"
};
for(int i = 0; i < expressions.Length; i++)
original = expressions[i].Replace(original, replacements[i]);
Edit 1:
Question changed to without spaces between the letters to match, wanted the same abcc from abc, I just reversed the order in which the regular expression was checked.
Regex[] expressions = new Regex[] {
new Regex(#"b"), //replaced by c
new Regex(#"a"), //replaced by ab
};
string[] replacements = new string[] {
"c",
"ab",
};
Edit 2:
Answer changed to reflect variable length to match, this matches based on order of patterns to check, checks for the pattern, then moves to new string
string original = "a bc";
Regex[] expressions = new Regex[] {
new Regex(#"a"), //replaced by ab
new Regex(#"b"), //replaced by c
};
string[] replacements = new string[] {
"ab",
"c",
};
string newString = string.Empty;
string workingString = string.Empty;
// Position of start point in string
int index = 0;
// Length to retrieve
int length = 1;
while(index < original.Length) {
// Retrieve a piece of the string
workingString = original.Substring(index, length);
// Whether the expression has been matched
bool found = false;
for(int i = 0; i < expressions.Length && !found; i++) {
if(expressions[i].Match(workingString).Success) {
// If expression matched, add the replacement value to the new string
newString += expressions[i].Replace(workingString, replacements[i]);
// Mark expression as found
found = true;
}
}
if(!found) {
// If not found, increase length (check for more than one character patterns)
length++;
// If the rest of the entire string doesn't match anything, move the character at **index** into the new string
if(length >= (original.Length - index)) {
newString += original.Substring(index, 1);
index++;
length = 1;
}
}
// If a match was found, start over at next position in string
else {
index += length;
length = 1;
}
}

Replace placeholders in order

I have a part of a URL like this:
/home/{value1}/something/{anotherValue}
Now i want to replace all between the brackets with values from a string-array.
I tried this RegEx pattern: \{[a-zA-Z_]\} but it doesn't work.
Later (in C#) I want to replace the first match with the first value of the array, second with the second.
Update: The /'s cant be used to separate. Only the placeholders {...} should be replaced.
Example: /home/before{value1}/and/{anotherValue}
String array: {"Tag", "1"}
Result: /home/beforeTag/and/1
I hoped it could works like this:
string input = #"/home/before{value1}/and/{anotherValue}";
string pattern = #"\{[a-zA-Z_]\}";
string[] values = {"Tag", "1"};
MatchCollection mc = Regex.Match(input, pattern);
for(int i, ...)
{
mc.Replace(values[i];
}
string result = mc.GetResult;
Edit:
Thank you Devendra D. Chavan and ipr101,
both solutions are greate!
You can try this code fragment,
// Begin with '{' followed by any number of word like characters and then end with '}'
var pattern = #"{\w*}";
var regex = new Regex(pattern);
var replacementArray = new [] {"abc", "cde", "def"};
var sourceString = #"/home/{value1}/something/{anotherValue}";
var matchCollection = regex.Matches(sourceString);
for (int i = 0; i < matchCollection.Count && i < replacementArray.Length; i++)
{
sourceString = sourceString.Replace(matchCollection[i].Value, replacementArray[i]);
}
[a-zA-Z_] describes a character class. For words, you'll have to add * at the end (any number of characters within a-zA-Z_.
Then, to have 'value1' captured, you'll need to add number support : [a-zA-Z0-9_]*, which can be summarized with: \w*
So try this one : {\w*}
But for replacing in C#, string.Split('/') might be easier as Fredrik proposed. Have a look at this too
You could use a delegate, something like this -
string[] strings = {"dog", "cat"};
int counter = -1;
string input = #"/home/{value1}/something/{anotherValue}";
Regex reg = new Regex(#"\{([a-zA-Z0-9]*)\}");
string result = reg.Replace(input, delegate(Match m) {
counter++;
return "{" + strings[counter] + "}";
});
My two cents:
// input string
string txt = "/home/{value1}/something/{anotherValue}";
// template replacements
string[] str_array = { "one", "two" };
// regex to match a template
Regex regex = new Regex("{[^}]*}");
// replace the first template occurrence for each element in array
foreach (string s in str_array)
{
txt = regex.Replace(txt, s, 1);
}
Console.Write(txt);

Categories

Resources