Convert String To camelCase from TitleCase C# - c#

I have a string that I converted to a TextInfo.ToTitleCase and removed the underscores and joined the string together. Now I need to change the first and only the first character in the string to lower case and for some reason, I can not figure out how to accomplish it.
class Program
{
static void Main(string[] args)
{
string functionName = "zebulans_nightmare";
TextInfo txtInfo = new CultureInfo("en-us", false).TextInfo;
functionName = txtInfo.ToTitleCase(functionName).Replace('_', ' ').Replace(" ", String.Empty);
Console.Out.WriteLine(functionName);
Console.ReadLine();
}
}
Results: ZebulansNightmare
Desired Results: zebulansNightmare
UPDATE:
class Program
{
static void Main(string[] args)
{
string functionName = "zebulans_nightmare";
TextInfo txtInfo = new CultureInfo("en-us", false).TextInfo;
functionName = txtInfo.ToTitleCase(functionName).Replace("_", string.Empty).Replace(" ", string.Empty);
functionName = $"{functionName.First().ToString().ToLowerInvariant()}{functionName.Substring(1)}";
Console.Out.WriteLine(functionName);
Console.ReadLine();
}
}
Produces the desired output.

You just need to lower the first char in the array. See this answer
Char.ToLowerInvariant(name[0]) + name.Substring(1)
As a side note, seeing as you are removing spaces you can replace the underscore with an empty string.
.Replace("_", string.Empty)

If you're using .NET Core 3 or .NET 5, you can call:
System.Text.Json.JsonNamingPolicy.CamelCase.ConvertName(someString)
Then you'll definitely get the same results as ASP.NET's own JSON serializer.

Implemented Bronumski's answer in an extension method (without replacing underscores).
public static class StringExtension
{
public static string ToCamelCase(this string str)
{
if(!string.IsNullOrEmpty(str) && str.Length > 1)
{
return char.ToLowerInvariant(str[0]) + str.Substring(1);
}
return str.ToLowerInvariant();
}
}
//Or
public static class StringExtension
{
public static string ToCamelCase(this string str) =>
string.IsNullOrEmpty(str) || str.Length < 2
? str.ToLowerInvariant()
: char.ToLowerInvariant(str[0]) + str.Substring(1);
}
and to use it:
string input = "ZebulansNightmare";
string output = input.ToCamelCase();

Here is my code, in case it is useful to anyone
// This converts to camel case
// Location_ID => locationId, and testLEFTSide => testLeftSide
static string CamelCase(string s)
{
var x = s.Replace("_", "");
if (x.Length == 0) return "null";
x = Regex.Replace(x, "([A-Z])([A-Z]+)($|[A-Z])",
m => m.Groups[1].Value + m.Groups[2].Value.ToLower() + m.Groups[3].Value);
return char.ToLower(x[0]) + x.Substring(1);
}
If you prefer Pascal-case use:
static string PascalCase(string s)
{
var x = CamelCase(s);
return char.ToUpper(x[0]) + x.Substring(1);
}

The following code works with acronyms as well. If it is the first word it converts the acronym to lower case (e.g., VATReturn to vatReturn), and otherwise leaves it as it is (e.g., ExcludedVAT to excludedVAT).
name = Regex.Replace(name, #"([A-Z])([A-Z]+|[a-z0-9_]+)($|[A-Z]\w*)",
m =>
{
return m.Groups[1].Value.ToLower() + m.Groups[2].Value.ToLower() + m.Groups[3].Value;
});

Example 01
public static string ToCamelCase(this string text)
{
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text);
}
Example 02
public static string ToCamelCase(this string text)
{
return string.Join(" ", text
.Split()
.Select(i => char.ToUpper(i[0]) + i.Substring(1)));
}
Example 03
public static string ToCamelCase(this string text)
{
char[] a = text.ToLower().ToCharArray();
for (int i = 0; i < a.Count(); i++)
{
a[i] = i == 0 || a[i - 1] == ' ' ? char.ToUpper(a[i]) : a[i];
}
return new string(a);
}

Adapted from Leonardo's answer:
static string PascalCase(string str) {
TextInfo cultInfo = new CultureInfo("en-US", false).TextInfo;
str = Regex.Replace(str, "([A-Z]+)", " $1");
str = cultInfo.ToTitleCase(str);
str = str.Replace(" ", "");
return str;
}
Converts to PascalCase by first adding a space before any group of capitals, and then converting to title case before removing all the spaces.

Here's my code, includes lowering all upper prefixes:
public static class StringExtensions
{
public static string ToCamelCase(this string str)
{
bool hasValue = !string.IsNullOrEmpty(str);
// doesn't have a value or already a camelCased word
if (!hasValue || (hasValue && Char.IsLower(str[0])))
{
return str;
}
string finalStr = "";
int len = str.Length;
int idx = 0;
char nextChar = str[idx];
while (Char.IsUpper(nextChar))
{
finalStr += char.ToLowerInvariant(nextChar);
if (len - 1 == idx)
{
// end of string
break;
}
nextChar = str[++idx];
}
// if not end of string
if (idx != len - 1)
{
finalStr += str.Substring(idx);
}
return finalStr;
}
}
Use it like this:
string camelCasedDob = "DOB".ToCamelCase();

If you are Ok with the Newtonsoft.JSON dependency, the following string extension method will help. The advantage of this approach is the serialization will work on par with standard WebAPI model binding serialization with high accuracy.
public static class StringExtensions
{
private class CamelCasingHelper : CamelCaseNamingStrategy
{
private CamelCasingHelper(){}
private static CamelCasingHelper helper =new CamelCasingHelper();
public static string ToCamelCase(string stringToBeConverted)
{
return helper.ResolvePropertyName(stringToBeConverted);
}
}
public static string ToCamelCase(this string str)
{
return CamelCasingHelper.ToCamelCase(str);
}
}
Here is the working fiddle
https://dotnetfiddle.net/pug8pP

In .Net 6 and above
public static class CamelCaseExtension
{
public static string ToCamelCase(this string str) =>
char.ToLowerInvariant(str[0]) + str[1..];
}

public static string CamelCase(this string str)
{
TextInfo cultInfo = new CultureInfo("en-US", false).TextInfo;
str = cultInfo.ToTitleCase(str);
str = str.Replace(" ", "");
return str;
}
This should work using System.Globalization

var camelCaseFormatter = new JsonSerializerSettings();
camelCaseFormatter.ContractResolver = new CamelCasePropertyNamesContractResolver();
JsonConvert.SerializeObject(object, camelCaseFormatter));

Strings are immutable, but we can use unsafe code to make it mutable though.
The string.Copy insured that the original string stays as is.
In order for these codes to run you have to allow unsafe code in your project.
public static unsafe string ToCamelCase(this string value)
{
if (value == null || value.Length == 0)
{
return value;
}
string result = string.Copy(value);
fixed (char* chr = result)
{
char valueChar = *chr;
*chr = char.ToLowerInvariant(valueChar);
}
return result;
}
This version modifies the original string, instead of returning a modified copy. This will be annoying though and totally uncommon. So make sure the XML comments are warning users about that.
public static unsafe void ToCamelCase(this string value)
{
if (value == null || value.Length == 0)
{
return value;
}
fixed (char* chr = value)
{
char valueChar = *chr;
*chr = char.ToLowerInvariant(valueChar);
}
return value;
}
Why use unsafe code though? Short answer... It's super fast.

Here's my code which is pretty simple. My major objective was to ensure that camel-casing was compatible with what ASP.NET serializes objects to, which the above examples don't guarantee.
public static class StringExtensions
{
public static string ToCamelCase(this string name)
{
var sb = new StringBuilder();
var i = 0;
// While we encounter upper case characters (except for the last), convert to lowercase.
while (i < name.Length - 1 && char.IsUpper(name[i + 1]))
{
sb.Append(char.ToLowerInvariant(name[i]));
i++;
}
// Copy the rest of the characters as is, except if we're still on the first character - which is always lowercase.
while (i < name.Length)
{
sb.Append(i == 0 ? char.ToLowerInvariant(name[i]) : name[i]);
i++;
}
return sb.ToString();
}
}

/// <summary>
/// Gets the camel case from snake case.
/// </summary>
/// <param name="snakeCase">The snake case.</param>
/// <returns></returns>
private string GetCamelCaseFromSnakeCase(string snakeCase)
{
string camelCase = string.Empty;
if(!string.IsNullOrEmpty(snakeCase))
{
string[] words = snakeCase.Split('_');
foreach (var word in words)
{
camelCase = string.Concat(camelCase, Char.ToUpperInvariant(word[0]) + word.Substring(1));
}
// making first character small case
camelCase = Char.ToLowerInvariant(camelCase[0]) + camelCase.Substring(1);
}
return camelCase;
}

I use This method to convert the string with separated by "_" to Camel Case
public static string ToCamelCase(string? s)
{
var nameArr = s?.ToLower().Split("_");
var str = "";
foreach (var name in nameArr.Select((value, i) => new { value, i }))
{
if(name.i >= 1)
{
str += string.Concat(name.value[0].ToString().ToUpper(), name.value.AsSpan(1));
}
else
{
str += name.value ;
}
}
return str;
}
u can change the separated by "_" with any other you want.

Simple and easy in build c#
using System;
using System.Globalization;
public class SamplesTextInfo {
public static void Main() {
// Defines the string with mixed casing.
string myString = "wAr aNd pEaCe";
// Creates a TextInfo based on the "en-US" culture.
TextInfo myTI = new CultureInfo("en-US",false).TextInfo;
// Changes a string to lowercase.
Console.WriteLine( "\"{0}\" to lowercase: {1}", myString, myTI.ToLower( myString ) );
// Changes a string to uppercase.
Console.WriteLine( "\"{0}\" to uppercase: {1}", myString, myTI.ToUpper( myString ) );
// Changes a string to titlecase.
Console.WriteLine( "\"{0}\" to titlecase: {1}", myString, myTI.ToTitleCase( myString ) );
}
}
/*
This code produces the following output.
"wAr aNd pEaCe" to lowercase: war and peace
"wAr aNd pEaCe" to uppercase: WAR AND PEACE
"wAr aNd pEaCe" to titlecase: War And Peace
*/

public static class StringExtension
{
public static string ToCamelCase(this string str)
{
return string.Join(" ", str
.Split()
.Select(i => char.ToUpper(i[0]) + i.Substring(1).ToLower()));
}
}

I had the same issue with titleCase so I just created one, hope this helps this is an extension method.
public static string ToCamelCase(this string text)
{
if (string.IsNullOrEmpty(text))
return text;
var separators = new[] { '_', ' ' };
var arr = text
.Split(separators)
.Where(word => !string.IsNullOrWhiteSpace(word));
var camelCaseArr = arr
.Select((word, i) =>
{
if (i == 0)
return word.ToLower();
var characterArr = word.ToCharArray()
.Select((character, characterIndex) => characterIndex == 0
? character.ToString().ToUpper()
: character.ToString().ToLower());
return string.Join("", characterArr);
});
return string.Join("", camelCaseArr);
}

Related

If a string contains a double character change it to another string C#

I created a Person Model:
Model Person = new Model();
Person.LastName = values[0];
[LastName is a string]
I would like to replace the values [0] which is "Anna" with another string value like "Frank" if it contains a double character, in this case "if Anna contains a double character, change the value
with another string".
how to do?
Write a helper function to test for consecutive equal characters:
private static bool HasDoubleCharacter(string s)
{
char? previous = null;
foreach (char ch in s) {
if (ch == previous) {
return true;
}
previous = ch;
}
return false;
}
The you can write
Model Person = new Model();
string name = values[0];
if (HasDoubleCharacter(name)) {
name = "Frank";
}
Person.LastName = name;
You could also create a new array containing only names with no double character and use that one instead:
Model Person = new Model();
string[] names = values
.Where(v => !HasDoubleCharacter(v))
.ToArray();
if (names.Length > 0) {
Person.LastName = names[0];
}
Same idea as in MichaƂ Turczyn post - a check for double character, but implemented via regular expressions:
using System.Text.RegularExpressions;
...
public static bool HasDoubleChar(string value) =>
value != null && Regex.IsMatch(value, #"(.)\1");
pattern (.)\1 explained:
(.) - group which contains an arbitrary character
\1 - the group #1 repeated again
Note, that we have some flexibility here: (\p{L})\1 will check for double letters only, not, say, spaces; (?i)(.)\1 will compare ignoring case (Aaron will be matched) etc.
then as usual
Person.LastName = HasDoubleChar(values[0])
? "Frank"
: values[0];
This could be achieved with easy extensions funciton for string:
public static class StringExtensions
{
public static bool HasDoubleChar(this string #this)
{
ArgumentNullException.ThrowIfNull(#this);
for (int i = 1; i < #this.Length; i++)
{
if (#this[i] == #this[i - 1])
{
return true;
}
}
return false;
}
}
and then you could use it:
Person.LastName = values[0].HasDoubleChar()
? "Frank"
: values[0];
public static string Do(string source, string replacement)
{
char c = source.ToLower()[0]; // do you care about case? E.g., Aaron.
for(int i = 1; i < source.Length; i++)
{
if (source.ToLower()[i] == c)
{
return replacement;
}
}
return source;
}
public static void Main()
{
string thing = "Aaron";
thing = Do(thing, "Frank");
}

I'd like to divide the strings to two array

I have a string data like "aaa.bbb.ccc" or "aaa.bbb.ccc.ddd".
If I split this like "aaa.bbb.ccc".split("."), it becomes "aaa", "bbb" and "ccc".
I want to divide this to just two strings like "aaa", "bbb.ccc".
I think I can do this by firstly dividing everything and rejoining it but it's not smart way.
Is there any way to set this more smoothly?
You can set the number of splitted parts:
string myString = "aaa.bbb.ccc";
int parts = 2;
string[] myParts = myString.Split(new string[] {"."}, parts, StringSplitOptions.None);
If you want to split on the first dot character, use Substring:
String value = "aaa.bbb.ccc";
Int32 firstDotIdx = value.IndexOf( '.' );
if( firstDotIdx > -1 ) {
return new String[] {
value.Substring( 0, firstDotIdx ),
value.Substring( firstDotIdx + 1 );
}
} else {
return new String[] {
value,
"";
}
}
If you have "aaa.bbb" then it will return { "aaa", "bbb" }.
If you have "aaa.bbb.ccc" then it will return { "aaa", "bbb.ccc" }.
If you have ".aaa.bbb" then it will return { "", "aaa.bbb" }.
If you have "aaa" then it will return { "aaa", "" }.
I have a bunch of extension methods for these kind of string manipulations. An example usage for your task would look like this.
var str = "aaa.bbb.ccc.ddd";
var result = new[] { str.TakeUntil("."), str.TakeFrom(".") };
And the extension pack looks like this. The functions` results will not include the search string itself, and if the search string is not present in the input, they will return the whole input as result (this is a convention which suites my needs for this edge case, could be changed).
public static string TakeUntil(this string s, string search)
{
if (string.IsNullOrEmpty(s)) return s;
var pos = s.IndexOf(search, StringComparison.OrdinalIgnoreCase);
if (pos >= 0)
return s.Substring(0, pos);
return s;
}
public static string TakeUntilLast(this string s, string search)
{
if (string.IsNullOrEmpty(s)) return s;
var pos = s.LastIndexOf(search, StringComparison.OrdinalIgnoreCase);
if (pos >= 0)
return s.Substring(0, pos);
return s;
}
public static string TakeFrom(this string s, string search)
{
if (string.IsNullOrEmpty(s)) return s;
var pos = s.IndexOf(search, StringComparison.OrdinalIgnoreCase);
if (pos >= 0)
return s.Substring(pos + search.Length);
return s;
}
public static string TakeFromLast(this string s, string search)
{
if (string.IsNullOrEmpty(s)) return s;
var pos = s.LastIndexOf(search, StringComparison.OrdinalIgnoreCase);
if (pos >= 0)
return s.Substring(pos + search.Length);
return s;
}

display format for results in console

I am trying to display my results as follows:
-.-|- [tab] kt
-.|-- [tab] nm
-.|-|- [tab] ntt
But this is my current output
-.-|-| kt
-.|--| nm
-.|-|-| [tab]ntt
There is a | at the end of every Morse code which I would like to remove since it is at the end.
Also because the user can input Morse code with space between dots and dashes - i noticed that it affects the alignment of the characters and not all of them get tabbed properly. The word tab isn't supposed to show i just wrote it in because I didn't know how to place a real tab.
private static readonly IDictionary<char, string> morseCode_alpha = new Dictionary<char, string>
{
{'a', ".-"},{'b',"-..."}, {'c',"-.-."}, {'d',"-.."}, {'e',"."},
{'f',"..-."}, {'g',"--."}, {'h',"...."},{'i',".."}, {'j',".---"},
{'k',"-.-"}, {'l',".-.."}, {'m',"--"}, {'n',"-."}, {'o',"---"},
{'p',".--."}, {'q',"--.-"}, {'r',".-."}, {'s',"..."}, {'t',"-"},
{'u',"..-"}, {'v',"...-"}, {'w',".--"}, {'x',"-..-"}, {'y',"-.--"}, {'z',"--.."}
};
private static string ConvertMorseToText(string symbolCode)
{
var builder = new StringBuilder(4 * symbolCode.Length);
foreach (char c in symbolCode)
builder.Append(morseCode_alpha[c]);
return builder.ToString();
}
private static string ConvertTextToMorse(char ch)
{
if (morseCode_alpha.Keys.Contains(ch))
return morseCode_alpha[ch];
else
return string.Empty;
}
private static string ConvertStringToMorse(string letters)
{
StringBuilder sb = new StringBuilder();
foreach (char ch in letters)
{
if (sb.Length != 0 && sb[sb.Length - 1] != ' ')
sb.Append("|");
sb.Append(ConvertTextToMorse(ch));
}
return sb.ToString();
}
private static IEnumerable<string> Permutations( string symbolCode)
{
int n = symbolCode.Length;
if (n == 0 || symbolCode.Length == 0)
yield return " ";
else
foreach (var entry in morseCode_alpha)
if (symbolCode.StartsWith(entry.Value))
foreach (string next in Permutations(symbolCode.Substring(entry.Value.Length)))
yield return entry.Key + next;
}
private static void Write( string rest)
{
string result = ConvertStringToMorse(rest);
Console.Write(result+"\t");
Console.WriteLine(rest);
}
static void Main(string[] args)
{
string morseInput;
string entered = "";
do
{
Console.WriteLine("Enter Morse Code: \n");
morseInput = Console.ReadLine().Replace(" ","");
bool isValid = Regex.IsMatch(morseInput, #"^[-.]+$");
if (isValid)
{
Console.WriteLine("\nAll permutations:\n");
string morse = ConvertMorseToText(entered);
string permutations = morseInput.Substring(morse.Length);
Write(permutations);
var nexts = new List<string>(Permutations(permutations));
foreach (string next in nexts)
Write(next);
}
else
{
Console.WriteLine("\nFormat of morse must be only dots and dashes.");
Console.WriteLine("Parameter name: "+morseInput+"\n");
}
}
while (morseInput.Length != 0);
}
And, to answer the other part of the question...
Tabstops are fixed for console writing, so it would be better to use something like String.PadRight
so, your code could be:
private static void Write(string rest)
{
string result = ConvertStringToMorse(rest);
Console.Write(result.PadRight(20));
Console.WriteLine(rest);
}
Draft version of the method:
private static string ConvertStringToMorse(string letters)
{
var result = string.Join("|",
letters
.Select(ConvertTextToMorse)
.Where(morse => !string.IsNullOrEmpty(morse)));
return result;
}
Update:
Please note that the entered variable is used only once: when defined - empty string is assigned. Then the ConvertMorseToText(entered) method is called: it always returns empty string for the empty string argument. After this assignment string permutations = morseInput.Substring(morse.Length); the permutations variable will store exactly the same value as morse variable (because morse.Length is always 0).
So, it seems that the entered variable and the ConvertMorseToText() method are useless (both can be safely removed):
static void Main(string[] args)
{
do
{
Console.WriteLine("Enter Morse Code: ");
string morseInput = Console.ReadLine();
if (string.IsNullOrWhiteSpace(morseInput))
{
// Empty or consists only of white-space characters
break;
}
morseInput = morseInput.Replace(" ", "");
bool isValid = Regex.IsMatch(morseInput, #"^[-.]+$");
if (isValid)
{
Console.WriteLine("All permutations:");
Console.WriteLine();
var nexts = Permutations(morseInput).ToList();
foreach (string next in nexts)
Write(next);
}
else
{
Console.WriteLine();
Console.WriteLine("Format of morse must be only dots and dashes.");
Console.WriteLine("Parameter name: {0}", morseInput);
}
}
while (true);
}
Update 2:
Consider using TryGetValue() method of Dictionary<TKey, TValue> instead of Keys.Contains and [] (indexer) i.e. do not perform look-up twice:
private static string ConvertTextToMorse(char ch)
{
string result;
return morseCode_alpha.TryGetValue(ch, out result) ? result : string.Empty;
}
Instead this code:
Console.Write(result+"\t");
Console.WriteLine(rest);
Use
Console.WriteLine("{0,-10}{1,-10}", result, rest);
Then you will see two columns (each max 10 charachters) with left alignment. Or remove "-" sign if you want right alignment.

String formatting using C#

Is there a way to remove every special character from a string like:
"\r\n 1802 S St Nw<br>\r\n Washington, DC 20009"
And to just write it like:
"1802 S St Nw, Washington, DC 20009"
To remove special characters:
public static string ClearSpecialChars(this string input)
{
foreach (var ch in new[] { "\r", "\n", "<br>", etc })
{
input = input.Replace(ch, String.Empty);
}
return input;
}
To replace all double space with single space:
public static string ClearDoubleSpaces(this string input)
{
while (input.Contains(" ")) // double
{
input = input.Replace(" ", " "); // with single
}
return input;
}
You also may split both methods into a single one:
public static string Clear(this string input)
{
return input
.ClearSpecialChars()
.ClearDoubleSpaces()
.Trim();
}
two ways, you can use RegEx, or you can use String.Replace(...)
Use the Regex.Replace() method, specifying all of the characters you want to remove as the pattern to match.
You can use the C# Trim() method, look here:
http://msdn.microsoft.com/de-de/library/d4tt83f9%28VS.80%29.aspx
System.Text.RegularExpressions.Regex.Replace("\"\\r\\n 1802 S St Nw<br>\\r\\n Washington, DC 20009\"",
#"(<br>)*?\\r\\n\s+", "");
Maybe something like this, using ASCII int values. Assumes all html tags will be closed.
public static class StringExtensions
{
public static string Clean(this string str)
{
string[] split = str.Split(' ');
List<string> strings = new List<string>();
foreach (string splitStr in split)
{
if (splitStr.Length > 0)
{
StringBuilder sb = new StringBuilder();
bool tagOpened = false;
foreach (char c in splitStr)
{
int iC = (int)c;
if (iC > 32)
{
if (iC == 60)
tagOpened = true;
if (!tagOpened)
sb.Append(c);
if (iC == 62)
tagOpened = false;
}
}
string result = sb.ToString();
if (result.Length > 0)
strings.Add(result);
}
}
return string.Join(" ", strings.ToArray());
}
}

C# Stripping / converting one or more characters

Is there a fast way (without having to explicitly looping through each character in a string) and either stripping or keeping it. In Visual FoxPro, there is a function CHRTRAN() that does it great. Its on a 1:1 character replacement, but if no character in the alternate position, its stripped from the final string. Ex
CHRTRAN( "This will be a test", "it", "X" )
will return
"ThXs wXll be a es"
Notice the original "i" is converted to "X", and lower case "t" is stripped out.
I looked at the replace for similar intent, but did not see an option to replace with nothing.
I'm looking to make some generic routines to validate multiple origins of data that have different types of input restrictions. Some of the data may be coming from external sources, so its not just textbox entry validation I need to test for.
Thanks
All you need is a couple of calls to String.Replace().
string s = "This will be a test";
s = s.Replace("i", "X");
s = s.Replace("t", "");
Note that Replace() returns a new string. It does not alter the string itself.
Does this what you want?
"This will be a test".Replace("i", "X").Replace("t", String.Empty)
Here is a simple implementation of the CHRTRAN function - it does not work if the string contains \0 and is quite messy. You could write a nicer one using loops, but I just wanted to try it using LINQ.
public static String ChrTran(String input, String source, String destination)
{
return source.Aggregate(
input,
(current, symbol) => current.Replace(
symbol,
destination.ElementAtOrDefault(source.IndexOf(symbol))),
preResult => preResult.Replace("\0", String.Empty));
}
And the you can use it.
// Returns "ThXs wXll be a es"
String output = ChrTran("This will be a test", "it", "X");
Just to have a clean solution - the same without LINQ and working for the \0 cases, too, and it is almost in place because of using a StringBuilder but won't modify the input, of course.
public static String ChrTran(String input, String source, String destination)
{
StringBuilder result = new StringBuilder(input);
Int32 minLength = Math.Min(source.Length, destination.Length);
for (Int32 i = 0; i < minLength; i++)
{
result.Replace(source[i], destination[i]);
}
for (Int32 i = minLength; i < searchPattern.Length; i++)
{
result.Replace(source[i].ToString(), String.Empty);
}
return result.ToString();
}
Null reference handling is missing.
Inspired by tvanfosson's solution, I gave LINQ a second shot.
public static String ChrTran(String input, String source, String destination)
{
return new String(input.
Where(symbol =>
!source.Contains(symbol) ||
source.IndexOf(symbol) < destination.Length).
Select(symbol =>
source.Contains(symbol)
? destination[source.IndexOf(symbol)]
: symbol).
ToArray());
}
Here was my final function and works perfectly as expected.
public static String ChrTran(String ToBeCleaned,
String ChangeThese,
String IntoThese)
{
String CurRepl = String.Empty;
for (int lnI = 0; lnI < ChangeThese.Length; lnI++)
{
if (lnI < IntoThese.Length)
CurRepl = IntoThese.Substring(lnI, 1);
else
CurRepl = String.Empty;
ToBeCleaned = ToBeCleaned.Replace(ChangeThese.Substring(lnI, 1), CurRepl);
}
return ToBeCleaned;
}
This is a case where I think using LINQ overcomplicates the matter. This is simple and to the point:
private static string Translate(string input, string from, string to)
{
StringBuilder sb = new StringBuilder();
foreach (char ch in input)
{
int i = from.IndexOf(ch);
if (from.IndexOf(ch) < 0)
{
sb.Append(ch);
}
else
{
if (i >= 0 && i < to.Length)
{
sb.Append(to[i]);
}
}
}
return sb.ToString();
}
To "replace with nothing", just replace with an empty string. This will give you:
String str = "This will be a test";
str = str.Replace("i", "X");
str = str.Replace("t","");
A more general version as a string extension. Like the others this does not do a translation in place since strings are immutable in C#, but instead returns a new string with the replacements as specified.
public static class StringExtensions
{
public static string Translate( this string source, string from, string to )
{
if (string.IsNullOrEmpty( source ) || string.IsNullOrEmpty( from ))
{
return source;
}
return string.Join( "", source.ToCharArray()
.Select( c => Translate( c, from, to ) )
.Where( c => c != null )
.ToArray() );
}
private static string Translate( char c, string from, string to )
{
int i = from != null ? from.IndexOf( c ) : -1;
if (i >= 0)
{
return (to != null && to.Length > i)
? to[i].ToString()
: null;
}
else
{
return c.ToString();
}
}
}

Categories