How-To Align String in Fixed Length String - c#

I've a String with Length = 100;
I need to center the text "Hello", in that string using whitespaces.
How can i do ?
thanks.

You can use the string padding methods and a little match to calcualte the center position:
var stringToCenter = "hello";
var totalLength = 100;
var centeredString =
stringToCenter.PadLeft(((totalLength - stringToCenter.Length) / 2)
+ stringToCenter.Length)
.PadRight(totalLength);
And you can move this logic into an extension method:
public static class StringExtensions{
public static string CenterString(this string stringToCenter, int totalLength)
{
return stringToCenter.PadLeft(((totalLength - stringToCenter.Length) / 2)
+ stringToCenter.Length)
.PadRight(totalLength);
}
}
And you can use it like
var centeredString = "hello".CenterString(100);
Demo .NETFiddle.

I would have added this as a comment to #nemesv's answer, but my lack of reputation on Stack Overflow prevents it.
The code in that answer causes more padding to be added on the right than the left. For example, in the code for that answer, the "h" in hello appears at the 43rd position instead of the 48th.
This revised code balances the padding.
var stringToCenter = "hello";
var stringToCenterLength = stringToCenter.Length;
var totalLength = 100;
var centeredString = stringToCenter.PadLeft(((totalLength - stringToCenterLength) / 2) + stringToCenterLength).PadRight(totalLength);

You can calculate string lenght and then apply appropriate padding by:
"".PadLeft() or "".PadRight()

I've expanded #nemesv's answer to contain an overload accepting a padding character so you can get something like:
################################# Hello World! #################################
Code:
using System;
public class Program
{
public void Main()
{
Console.WriteLine(" Hello World! ".CenterString(80, '#'));
}
}
public static class StringExtensions
{
public static string CenterString(this string stringToCenter, int totalLength)
{
return stringToCenter.PadLeft(
((totalLength - stringToCenter.Length) / 2)
+ stringToCenter.Length).PadRight(totalLength);
}
public static string CenterString(this string stringToCenter,
int totalLength,
char paddingCharacter)
{
return stringToCenter.PadLeft(
((totalLength - stringToCenter.Length) / 2) + stringToCenter.Length,
paddingCharacter).PadRight(totalLength, paddingCharacter);
}
}
Example: .NETFiddle

Related

How to convert a big float into a string with commas without rounding

I have a large float that I want to convert into a string with commas without rounding.
Here is what I have:
String.Format("{0:#,###}", val);
This turns 17154177 into 17,154,180
I would like to keep the commas but not round at the end using c#.
This may be what you're looking for
using System;
class MainClass {
public static void Main (string[] args) {
float original = 17154177;
// 1. Convert the number to a string
string value = original.ToString("R");
// 2. Reverse the string
string reversed = Reverse(value);
// 3. Add the comma on each third number, backwards
string formatted = "";
for(int i = 0; i < reversed.Length; i++) {
if ((i+1) % 3 == 0) {
formatted += reversed[i] + ",";
} else {
formatted += reversed[i];
}
}
// 4. Reverse it back to the original order
formatted = Reverse(formatted);
Console.WriteLine (formatted);
}
/* Reverses a string */
public static string Reverse(string text)
{
char[] cArray = text.ToCharArray();
string reverse = String.Empty;
for (int i = cArray.Length - 1; i > -1; i--)
{
reverse += cArray[i];
}
return reverse;
}
}
I got the reverse method from this question.
Change your data type to decimal (28-29 significant digits) to have higher precision compared to float (7 digits).
Or you can change it to var. It will let the compiler figure out the best data type to use.
var number = 17154177;
Console.WriteLine(String.Format("{0:#,###}", number));
See this fiddler link, working code

Remove characters from a string after a certain condition is met [duplicate]

I have this string: ABCDEFGHIJ
I need to replace from position 4 to position 5 with the string ZX
It will look like this: ABCZXFGHIJ
But not to use with string.replace("DE","ZX") - I need to use with position
How can I do it?
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");
The easiest way to add and remove ranges in a string is to use the StringBuilder.
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
An alternative is to use String.Substring, but I think the StringBuilder code gets more readable.
ReplaceAt(int index, int length, string replace)
Here's an extension method that doesn't use StringBuilder or Substring. This method also allows the replacement string to extend past the length of the source string.
//// str - the source string
//// index- the start location to replace at (0-based)
//// length - the number of characters to be removed before inserting
//// replace - the string that is replacing characters
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return str.Remove(index, Math.Min(length, str.Length - index))
.Insert(index, replace);
}
When using this function, if you want the entire replacement string to replace as many characters as possible, then set length to the length of the replacement string:
"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"
Otherwise, you can specify the amount of characters that will be removed:
"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"
If you specify the length to be 0, then this function acts just like the insert function:
"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"
I guess this is more efficient since the StringBuilder class need not be initialized and since it uses more basic operations. Please correct me if I am wrong. :)
If you care about performance, then the thing you want to avoid here are allocations. And if you're on .Net Core 2.1+, then you can, by using the string.Create method:
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return string.Create(str.Length - length + replace.Length, (str, index, length, replace),
(span, state) =>
{
state.str.AsSpan().Slice(0, state.index).CopyTo(span);
state.replace.AsSpan().CopyTo(span.Slice(state.index));
state.str.AsSpan().Slice(state.index + state.length).CopyTo(span.Slice(state.index + state.replace.Length));
});
}
This approach is harder to understand than the alternatives, but it's the only one that will allocate only one object per call: the newly created string.
Use String.Substring() (details here) to cut left part, then your replacement, then right part. Play with indexes until you get it right :)
Something like:
string replacement=original.Substring(0,start)+
rep+original.Substring(start+rep.Length);
string s = "ABCDEFG";
string t = "st";
s = s.Remove(4, t.Length);
s = s.Insert(4, t);
As an extension method.
public static class StringBuilderExtension
{
public static string SubsituteString(this string OriginalStr, int index, int length, string SubsituteStr)
{
return new StringBuilder(OriginalStr).Remove(index, length).Insert(index, SubsituteStr).ToString();
}
}
You could try something link this:
string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);
Like other have mentioned the Substring() function is there for a reason:
static void Main(string[] args)
{
string input = "ABCDEFGHIJ";
string output = input.Overwrite(3, "ZX"); // 4th position has index 3
// ABCZXFGHIJ
}
public static string Overwrite(this string text, int position, string new_text)
{
return text.Substring(0, position) + new_text + text.Substring(position + new_text.Length);
}
Also I timed this against the StringBuilder solution and got 900 tics vs. 875. So it is slightly slower.
Yet another
public static string ReplaceAtPosition(this string self, int position, string newValue)
{
return self.Remove(position, newValue.Length).Insert(position, newValue);
}
With the help of this post, I create following function with additional length checks
public string ReplaceStringByIndex(string original, string replaceWith, int replaceIndex)
{
if (original.Length >= (replaceIndex + replaceWith.Length))
{
StringBuilder rev = new StringBuilder(original);
rev.Remove(replaceIndex, replaceWith.Length);
rev.Insert(replaceIndex, replaceWith);
return rev.ToString();
}
else
{
throw new Exception("Wrong lengths for the operation");
}
}
All others answers don't work if the string contains Unicode char (like Emojis) because an Unicode char weight more bytes than a char.
Example : the emoji '🎶' converted to bytes, will weight the equivalent of 2 chars. So, if the unicode char is placed at the beginning of your string, offset parameter will be shifted).
With this topic, i extend the StringInfo class to Replace by position keeping the Nick Miller's algorithm to avoid that :
public static class StringInfoUtils
{
public static string ReplaceByPosition(this string str, string replaceBy, int offset, int count)
{
return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
}
public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
{
return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
}
public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
{
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
offset + count < str.LengthInTextElements
? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
: ""
));
}
public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
{
if (string.IsNullOrEmpty(str?.String))
return new StringInfo(insertStr);
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
insertStr,
str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
));
}
}
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();
Let me explain my solution.
Given the problem statement of altering a string in its two specific position (“position 4 to position 5”) with two character ‘Z’ and ‘X’ and the ask is to use the position index to alter the string and not string Replace() method(may be because of the possibility of repetition of some characters in the actual string), I would prefer to use minimalist approach to achieve the goal over using Substring() and string Concat() or string Remove() and Insert() approach. Though all those solutions will serve the purpose in attaining the same goal, but it just depends on personal choice and philosophy of settling with minimalist approach.
Coming back to my solution mention above, if we take a closer look of string and StringBuilder, both of them internally treats a given string as an array of characters. If we look at the implementation of StringBuilder it maintains an internal variable something like “internal char[] m_ChunkChars;” to capture the given string. Now since this is an internal variable, we cannot directly access the same. For external world, to be able to access and alter that character array, StringBuilder exposes them through indexer property which looks something like below
[IndexerName("Chars")]
public char this[int index]
{
get
{
StringBuilder stringBuilder = this;
do
{
// … some code
return stringBuilder.m_ChunkChars[index1];
// … some more code
}
}
set
{
StringBuilder stringBuilder = this;
do
{
//… some code
stringBuilder.m_ChunkChars[index1] = value;
return;
// …. Some more code
}
}
}
My solution mentioned above leverage this indexer capability to directly alter the internally maintained character array which IMO is efficient and minimalist.
BTW; we can rewrite the above solution more elaborately something like below
string myString = "ABCDEFGHIJ";
StringBuilder tempString = new StringBuilder(myString);
tempString[3] = 'Z';
tempString[4] = 'X';
string modifiedString = tempString.ToString();
In this context also would like to mention that in case of string it also have indexer property as a means to expose its internal character array, but in this case it only has Getter property (and no Setter) as string is immutable in nature. And that is why we need to use StringBuilder to alter the character array.
[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }
And last but not the least this solution is only best fit for this specific problem where the ask is to replace only few characters with a known position index upfront. It may not be the best fit when the requirement is to alter a fairly lengthy string i.e. number of characters to alter are large in numbers.
I was looking for a solution with following requirements:
use only a single, one-line expression
use only system builtin methods (no custom implemented utility)
Solution 1
The solution that best suits me is this:
// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();
This uses StringBuilder.Replace(oldChar, newChar, position, count)
Solution 2
The other solution that satisfies my requirements is to use Substring with concatenation:
string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);
This is OK too. I guess it's not as efficient as the first one performance wise (due to unnecessary string concatenation). But premature optimization is the root of all evil.
So pick the one that you like the most :)
hello this code helps me:
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
It's better to use the String.substr().
Like this:
ReplString = GivenStr.substr(0, PostostarRelStr)
+ GivenStr(PostostarRelStr, ReplString.lenght());
String timestamp = "2019-09-18 21.42.05.000705";
String sub1 = timestamp.substring(0, 19).replace('.', ':');
String sub2 = timestamp.substring(19, timestamp.length());
System.out.println("Original String "+ timestamp);
System.out.println("Replaced Value "+ sub1+sub2);
Here is a simple extension method:
public static class StringBuilderExtensions
{
public static StringBuilder Replace(this StringBuilder sb, int position, string newString)
=> sb.Replace(position, newString.Length, newString);
public static StringBuilder Replace(this StringBuilder sb, int position, int length, string newString)
=> (newString.Length <= length)
? sb.Remove(position, newString.Length).Insert(position, newString)
: sb.Remove(position, length).Insert(position, newString.Substring(0, length));
}
Use it like this:
var theString = new string(' ', 10);
var sb = new StringBuilder(theString);
sb.Replace(5, "foo");
return sb.ToString();
I do this
Dim QTT As Double
If IsDBNull(dr.Item(7)) Then
QTT = 0
Else
Dim value As String = dr.Item(7).ToString()
Dim posicpoint As Integer = value.LastIndexOf(".")
If posicpoint > 0 Then
Dim v As New Text.StringBuilder(value)
v.Remove(posicpoint, 1)
v.Insert(posicpoint, ",")
QTT = Convert.ToDouble(v.ToString())
Else
QTT = Convert.ToDouble(dr.Item(7).ToString())
End If
Console.WriteLine(QTT.ToString())
End If
Suppose we know the index of string to be replace.
string s = "ABCDEFGDEJ";
string z = "DE";
int i = s.IndexOf(z);
if(i == 3)
s = s.Remove(3,z.Length).Insert(3,"ZX");
//s = ABCZXFGDEJ
I believe the simplest way would be this:(without stringbuilder)
string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;
for (byte i = 3; i <= 4; i++, j++)
{
myString = myString.Replace(myString[i], replacementChars[j]);
}
This works because a variable of type string can be treated as an array of char variables.
You can, for example refer to the second character of a string variable with name "myString" as myString[1]

How to insert/remove hyphen to/from a plain string in c#?

I have a string like this;
string text = "6A7FEBFCCC51268FBFF";
And I have one method for which I want to insert the logic for appending the hyphen after 4 characters to 'text' variable. So, the output should be like this;
6A7F-EBFC-CC51-268F-BFF
Appending hyphen to above 'text' variable logic should be inside this method;
public void GetResultsWithHyphen
{
// append hyphen after 4 characters logic goes here
}
And I want also remove the hyphen from a given string such as 6A7F-EBFC-CC51-268F-BFF. So, removing hyphen from a string logic should be inside this method;
public void GetResultsWithOutHyphen
{
// Removing hyphen after 4 characters logic goes here
}
How can I do this in C# (for desktop app)?
What is the best way to do this?
Appreciate everyone's answer in advance.
GetResultsWithOutHyphen is easy (and should return a string instead of void
public string GetResultsWithOutHyphen(string input)
{
// Removing hyphen after 4 characters logic goes here
return input.Replace("-", "");
}
for GetResultsWithHyphen, there may be slicker ways to do it, but here's one way:
public string GetResultsWithHyphen(string input)
{
// append hyphen after 4 characters logic goes here
string output = "";
int start = 0;
while (start < input.Length)
{
output += input.Substring(start, Math.Min(4,input.Length - start)) + "-";
start += 4;
}
// remove the trailing dash
return output.Trim('-');
}
Use regex:
public String GetResultsWithHyphen(String inputString)
{
return Regex.Replace(inputString, #"(\w{4})(\w{4})(\w{4})(\w{4})(\w{3})",
#"$1-$2-$3-$4-$5");
}
and for removal:
public String GetResultsWithOutHyphen(String inputString)
{
return inputString.Replace("-", "");
}
Here's the shortest regex I could come up with. It will work on strings of any length. Note that the \B token will prevent it from matching at the end of a string, so you don't have to trim off an extra hyphen as with some answers above.
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string text = "6A7FEBFCCC51268FBFF";
for (int i = 0; i <= text.Length;i++ )
Console.WriteLine(hyphenate(text.Substring(0, i)));
}
static string hyphenate(string s)
{
var re = new Regex(#"(\w{4}\B)");
return re.Replace (s, "$1-");
}
static string dehyphenate (string s)
{
return s.Replace("-", "");
}
}
}
var hyphenText = new string(
text
.SelectMany((i, ch) => i%4 == 3 && i != text.Length-1 ? new[]{ch, '-'} : new[]{ch})
.ToArray()
)
something along the lines of:
public string GetResultsWithHyphen(string inText)
{
var counter = 0;
var outString = string.Empty;
while (counter < inText.Length)
{
if (counter % 4 == 0)
outString = string.Format("{0}-{1}", outString, inText.Substring(counter, 1));
else
outString += inText.Substring(counter, 1);
counter++;
}
return outString;
}
This is rough code and may not be perfectly, syntactically correct
public static string GetResultsWithHyphen(string str) {
return Regex.Replace(str, "(.{4})", "$1-");
//if you don't want trailing -
//return Regex.Replace(str, "(.{4})(?!$)", "$1-");
}
public static string GetResultsWithOutHyphen(string str) {
//if you just want to remove the hyphens:
//return input.Replace("-", "");
//if you REALLY want to remove hyphens only if they occur after 4 places:
return Regex.Replace(str, "(.{4})-", "$1");
}
For removing:
String textHyphenRemoved=text.Replace('-',''); should remove all of the hyphens
for adding
StringBuilder strBuilder = new StringBuilder();
int startPos = 0;
for (int i = 0; i < text.Length / 4; i++)
{
startPos = i * 4;
strBuilder.Append(text.Substring(startPos,4));
//if it isn't the end of the string add a hyphen
if(text.Length-startPos!=4)
strBuilder.Append("-");
}
//add what is left
strBuilder.Append(text.Substring(startPos, 4));
string textWithHyphens = strBuilder.ToString();
Do note that my adding code is untested.
GetResultsWithOutHyphen method
public string GetResultsWithOutHyphen(string input)
{
return input.Replace("-", "");
}
GetResultsWithOutHyphen method
You could pass a variable instead of four for flexibility.
public string GetResultsWithHyphen(string input)
{
string output = "";
int start = 0;
while (start < input.Length)
{
char bla = input[start];
output += bla;
start += 1;
if (start % 4 == 0)
{
output += "-";
}
}
return output;
}
This worked for me when I had a value for a social security number (123456789) and needed it to display as (123-45-6789) in a listbox.
ListBox1.Items.Add("SS Number : " & vbTab & Format(SSNArray(i), "###-##-####"))
In this case I had an array of Social Security Numbers. This line of code alters the formatting to put a hyphen in.
Callee
public static void Main()
{
var text = new Text("THISisJUSTanEXAMPLEtext");
var convertText = text.Convert();
Console.WriteLine(convertText);
}
Caller
public class Text
{
private string _text;
private int _jumpNo = 4;
public Text(string text)
{
_text = text;
}
public Text(string text, int jumpNo)
{
_text = text;
_jumpNo = jumpNo < 1 ? _jumpNo : jumpNo;
}
public string Convert()
{
if (string.IsNullOrEmpty(_text))
{
return string.Empty;
}
if (_text.Length < _jumpNo)
{
return _text;
}
var convertText = _text.Substring(0, _jumpNo);
int start = _jumpNo;
while (start < _text.Length)
{
convertText += "-" + _text.Substring(start, Math.Min(_jumpNo, _text.Length - start));
start += _jumpNo;
}
return convertText;
}
}

How to replace part of string by position?

I have this string: ABCDEFGHIJ
I need to replace from position 4 to position 5 with the string ZX
It will look like this: ABCZXFGHIJ
But not to use with string.replace("DE","ZX") - I need to use with position
How can I do it?
string s = "ABCDEFGH";
s= s.Remove(3, 2).Insert(3, "ZX");
The easiest way to add and remove ranges in a string is to use the StringBuilder.
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
An alternative is to use String.Substring, but I think the StringBuilder code gets more readable.
ReplaceAt(int index, int length, string replace)
Here's an extension method that doesn't use StringBuilder or Substring. This method also allows the replacement string to extend past the length of the source string.
//// str - the source string
//// index- the start location to replace at (0-based)
//// length - the number of characters to be removed before inserting
//// replace - the string that is replacing characters
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return str.Remove(index, Math.Min(length, str.Length - index))
.Insert(index, replace);
}
When using this function, if you want the entire replacement string to replace as many characters as possible, then set length to the length of the replacement string:
"0123456789".ReplaceAt(7, 5, "Hello") = "0123456Hello"
Otherwise, you can specify the amount of characters that will be removed:
"0123456789".ReplaceAt(2, 2, "Hello") = "01Hello456789"
If you specify the length to be 0, then this function acts just like the insert function:
"0123456789".ReplaceAt(4, 0, "Hello") = "0123Hello456789"
I guess this is more efficient since the StringBuilder class need not be initialized and since it uses more basic operations. Please correct me if I am wrong. :)
If you care about performance, then the thing you want to avoid here are allocations. And if you're on .Net Core 2.1+, then you can, by using the string.Create method:
public static string ReplaceAt(this string str, int index, int length, string replace)
{
return string.Create(str.Length - length + replace.Length, (str, index, length, replace),
(span, state) =>
{
state.str.AsSpan().Slice(0, state.index).CopyTo(span);
state.replace.AsSpan().CopyTo(span.Slice(state.index));
state.str.AsSpan().Slice(state.index + state.length).CopyTo(span.Slice(state.index + state.replace.Length));
});
}
This approach is harder to understand than the alternatives, but it's the only one that will allocate only one object per call: the newly created string.
Use String.Substring() (details here) to cut left part, then your replacement, then right part. Play with indexes until you get it right :)
Something like:
string replacement=original.Substring(0,start)+
rep+original.Substring(start+rep.Length);
string s = "ABCDEFG";
string t = "st";
s = s.Remove(4, t.Length);
s = s.Insert(4, t);
As an extension method.
public static class StringBuilderExtension
{
public static string SubsituteString(this string OriginalStr, int index, int length, string SubsituteStr)
{
return new StringBuilder(OriginalStr).Remove(index, length).Insert(index, SubsituteStr).ToString();
}
}
You could try something link this:
string str = "ABCDEFGHIJ";
str = str.Substring(0, 2) + "ZX" + str.Substring(5);
Like other have mentioned the Substring() function is there for a reason:
static void Main(string[] args)
{
string input = "ABCDEFGHIJ";
string output = input.Overwrite(3, "ZX"); // 4th position has index 3
// ABCZXFGHIJ
}
public static string Overwrite(this string text, int position, string new_text)
{
return text.Substring(0, position) + new_text + text.Substring(position + new_text.Length);
}
Also I timed this against the StringBuilder solution and got 900 tics vs. 875. So it is slightly slower.
Yet another
public static string ReplaceAtPosition(this string self, int position, string newValue)
{
return self.Remove(position, newValue.Length).Insert(position, newValue);
}
With the help of this post, I create following function with additional length checks
public string ReplaceStringByIndex(string original, string replaceWith, int replaceIndex)
{
if (original.Length >= (replaceIndex + replaceWith.Length))
{
StringBuilder rev = new StringBuilder(original);
rev.Remove(replaceIndex, replaceWith.Length);
rev.Insert(replaceIndex, replaceWith);
return rev.ToString();
}
else
{
throw new Exception("Wrong lengths for the operation");
}
}
All others answers don't work if the string contains Unicode char (like Emojis) because an Unicode char weight more bytes than a char.
Example : the emoji '🎶' converted to bytes, will weight the equivalent of 2 chars. So, if the unicode char is placed at the beginning of your string, offset parameter will be shifted).
With this topic, i extend the StringInfo class to Replace by position keeping the Nick Miller's algorithm to avoid that :
public static class StringInfoUtils
{
public static string ReplaceByPosition(this string str, string replaceBy, int offset, int count)
{
return new StringInfo(str).ReplaceByPosition(replaceBy, offset, count).String;
}
public static StringInfo ReplaceByPosition(this StringInfo str, string replaceBy, int offset, int count)
{
return str.RemoveByTextElements(offset, count).InsertByTextElements(offset, replaceBy);
}
public static StringInfo RemoveByTextElements(this StringInfo str, int offset, int count)
{
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
offset + count < str.LengthInTextElements
? str.SubstringByTextElements(offset + count, str.LengthInTextElements - count - offset)
: ""
));
}
public static StringInfo InsertByTextElements(this StringInfo str, int offset, string insertStr)
{
if (string.IsNullOrEmpty(str?.String))
return new StringInfo(insertStr);
return new StringInfo(string.Concat(
str.SubstringByTextElements(0, offset),
insertStr,
str.LengthInTextElements - offset > 0 ? str.SubstringByTextElements(offset, str.LengthInTextElements - offset) : ""
));
}
}
string myString = "ABCDEFGHIJ";
string modifiedString = new StringBuilder(myString){[3]='Z', [4]='X'}.ToString();
Let me explain my solution.
Given the problem statement of altering a string in its two specific position (“position 4 to position 5”) with two character ‘Z’ and ‘X’ and the ask is to use the position index to alter the string and not string Replace() method(may be because of the possibility of repetition of some characters in the actual string), I would prefer to use minimalist approach to achieve the goal over using Substring() and string Concat() or string Remove() and Insert() approach. Though all those solutions will serve the purpose in attaining the same goal, but it just depends on personal choice and philosophy of settling with minimalist approach.
Coming back to my solution mention above, if we take a closer look of string and StringBuilder, both of them internally treats a given string as an array of characters. If we look at the implementation of StringBuilder it maintains an internal variable something like “internal char[] m_ChunkChars;” to capture the given string. Now since this is an internal variable, we cannot directly access the same. For external world, to be able to access and alter that character array, StringBuilder exposes them through indexer property which looks something like below
[IndexerName("Chars")]
public char this[int index]
{
get
{
StringBuilder stringBuilder = this;
do
{
// … some code
return stringBuilder.m_ChunkChars[index1];
// … some more code
}
}
set
{
StringBuilder stringBuilder = this;
do
{
//… some code
stringBuilder.m_ChunkChars[index1] = value;
return;
// …. Some more code
}
}
}
My solution mentioned above leverage this indexer capability to directly alter the internally maintained character array which IMO is efficient and minimalist.
BTW; we can rewrite the above solution more elaborately something like below
string myString = "ABCDEFGHIJ";
StringBuilder tempString = new StringBuilder(myString);
tempString[3] = 'Z';
tempString[4] = 'X';
string modifiedString = tempString.ToString();
In this context also would like to mention that in case of string it also have indexer property as a means to expose its internal character array, but in this case it only has Getter property (and no Setter) as string is immutable in nature. And that is why we need to use StringBuilder to alter the character array.
[IndexerName("Chars")]
public extern char this[int index] { [SecuritySafeCritical, __DynamicallyInvokable, MethodImpl(MethodImplOptions.InternalCall)] get; }
And last but not the least this solution is only best fit for this specific problem where the ask is to replace only few characters with a known position index upfront. It may not be the best fit when the requirement is to alter a fairly lengthy string i.e. number of characters to alter are large in numbers.
I was looking for a solution with following requirements:
use only a single, one-line expression
use only system builtin methods (no custom implemented utility)
Solution 1
The solution that best suits me is this:
// replace `oldString[i]` with `c`
string newString = new StringBuilder(oldString).Replace(oldString[i], c, i, 1).ToString();
This uses StringBuilder.Replace(oldChar, newChar, position, count)
Solution 2
The other solution that satisfies my requirements is to use Substring with concatenation:
string newString = oldStr.Substring(0, i) + c + oldString.Substring(i+1, oldString.Length);
This is OK too. I guess it's not as efficient as the first one performance wise (due to unnecessary string concatenation). But premature optimization is the root of all evil.
So pick the one that you like the most :)
hello this code helps me:
var theString = "ABCDEFGHIJ";
var aStringBuilder = new StringBuilder(theString);
aStringBuilder.Remove(3, 2);
aStringBuilder.Insert(3, "ZX");
theString = aStringBuilder.ToString();
It's better to use the String.substr().
Like this:
ReplString = GivenStr.substr(0, PostostarRelStr)
+ GivenStr(PostostarRelStr, ReplString.lenght());
String timestamp = "2019-09-18 21.42.05.000705";
String sub1 = timestamp.substring(0, 19).replace('.', ':');
String sub2 = timestamp.substring(19, timestamp.length());
System.out.println("Original String "+ timestamp);
System.out.println("Replaced Value "+ sub1+sub2);
Here is a simple extension method:
public static class StringBuilderExtensions
{
public static StringBuilder Replace(this StringBuilder sb, int position, string newString)
=> sb.Replace(position, newString.Length, newString);
public static StringBuilder Replace(this StringBuilder sb, int position, int length, string newString)
=> (newString.Length <= length)
? sb.Remove(position, newString.Length).Insert(position, newString)
: sb.Remove(position, length).Insert(position, newString.Substring(0, length));
}
Use it like this:
var theString = new string(' ', 10);
var sb = new StringBuilder(theString);
sb.Replace(5, "foo");
return sb.ToString();
I do this
Dim QTT As Double
If IsDBNull(dr.Item(7)) Then
QTT = 0
Else
Dim value As String = dr.Item(7).ToString()
Dim posicpoint As Integer = value.LastIndexOf(".")
If posicpoint > 0 Then
Dim v As New Text.StringBuilder(value)
v.Remove(posicpoint, 1)
v.Insert(posicpoint, ",")
QTT = Convert.ToDouble(v.ToString())
Else
QTT = Convert.ToDouble(dr.Item(7).ToString())
End If
Console.WriteLine(QTT.ToString())
End If
Suppose we know the index of string to be replace.
string s = "ABCDEFGDEJ";
string z = "DE";
int i = s.IndexOf(z);
if(i == 3)
s = s.Remove(3,z.Length).Insert(3,"ZX");
//s = ABCZXFGDEJ
I believe the simplest way would be this:(without stringbuilder)
string myString = "ABCDEFGHIJ";
char[] replacementChars = {'Z', 'X'};
byte j = 0;
for (byte i = 3; i <= 4; i++, j++)
{
myString = myString.Replace(myString[i], replacementChars[j]);
}
This works because a variable of type string can be treated as an array of char variables.
You can, for example refer to the second character of a string variable with name "myString" as myString[1]

How do I replace the *first instance* of a string in .NET?

I want to replace the first occurrence in a given string.
How can I accomplish this in .NET?
string ReplaceFirst(string text, string search, string replace)
{
int pos = text.IndexOf(search);
if (pos < 0)
{
return text;
}
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}
Example:
string str = "The brown brown fox jumps over the lazy dog";
str = ReplaceFirst(str, "brown", "quick");
EDIT: As #itsmatt mentioned, there's also Regex.Replace(String, String, Int32), which can do the same, but is probably more expensive at runtime, since it's utilizing a full featured parser where my method does one find and three string concatenations.
EDIT2: If this is a common task, you might want to make the method an extension method:
public static class StringExtension
{
public static string ReplaceFirst(this string text, string search, string replace)
{
// ...same as above...
}
}
Using the above example it's now possible to write:
str = str.ReplaceFirst("brown", "quick");
As itsmatt said Regex.Replace is a good choice for this however to make his answer more complete I will fill it in with a code sample:
using System.Text.RegularExpressions;
...
Regex regex = new Regex("foo");
string result = regex.Replace("foo1 foo2 foo3 foo4", "bar", 1);
// result = "bar1 foo2 foo3 foo4"
The third parameter, set to 1 in this case, is the number of occurrences of the regex pattern that you want to replace in the input string from the beginning of the string.
I was hoping this could be done with a static Regex.Replace overload but unfortunately it appears you need a Regex instance to accomplish it.
Take a look at Regex.Replace.
using System.Text.RegularExpressions;
RegEx MyRegEx = new RegEx("F");
string result = MyRegex.Replace(InputString, "R", 1);
will find first F in InputString and replace it with R.
Taking the "first only" into account, perhaps:
int index = input.IndexOf("AA");
if (index >= 0) output = input.Substring(0, index) + "XQ" +
input.Substring(index + 2);
?
Or more generally:
public static string ReplaceFirstInstance(this string source,
string find, string replace)
{
int index = source.IndexOf(find);
return index < 0 ? source : source.Substring(0, index) + replace +
source.Substring(index + find.Length);
}
Then:
string output = input.ReplaceFirstInstance("AA", "XQ");
C# extension method that will do this:
public static class StringExt
{
public static string ReplaceFirstOccurrence(this string s, string oldValue, string newValue)
{
int i = s.IndexOf(oldValue);
return s.Remove(i, oldValue.Length).Insert(i, newValue);
}
}
In C# syntax:
int loc = original.IndexOf(oldValue);
if( loc < 0 ) {
return original;
}
return original.Remove(loc, oldValue.Length).Insert(loc, newValue);
Assumes that AA only needs to be replaced if it is at the very start of the string:
var newString;
if(myString.StartsWith("AA"))
{
newString ="XQ" + myString.Substring(2);
}
If you need to replace the first occurrence of AA, whether the string starts with it or not, go with the solution from Marc.
And because there is also VB.NET to consider, I would like to offer up:
Private Function ReplaceFirst(ByVal text As String, ByVal search As String, ByVal replace As String) As String
Dim pos As Integer = text.IndexOf(search)
If pos >= 0 Then
Return text.Substring(0, pos) + replace + text.Substring(pos + search.Length)
End If
Return text
End Function
One of the overloads of Regex.Replace takes an int for "The maximum number of times the replacement can occur". Obviously, using Regex.Replace for plain text replacement may seem like overkill, but it's certainly concise:
string output = (new Regex("AA")).Replace(input, "XQ", 1);
For anyone that doesn't mind a reference to Microsoft.VisualBasic, there is the Replace Method:
string result = Microsoft.VisualBasic.Strings.Replace("111", "1", "0", 2, 1); // "101"
This example abstracts away the substrings (but is slower), but is probably much fast than a RegEx:
var parts = contents.ToString().Split(new string[] { "needle" }, 2, StringSplitOptions.None);
return parts[0] + "replacement" + parts[1];
Updated extension method utilizing Span to minimize new string creation
public static string ReplaceFirstOccurrence(this string source, string search, string replace) {
int index = source.IndexOf(search);
if (index < 0) return source;
var sourceSpan = source.AsSpan();
return string.Concat(sourceSpan.Slice(0, index), replace, sourceSpan.Slice(index + search.Length));
}
With ranges and C# 10 we can do:
public static string ReplaceFirst(this string text, string search, string replace)
{
int pos = text.IndexOf(search, StringComparison.Ordinal);
return pos < 0 ? text : string.Concat(text[..pos], replace, text.AsSpan(pos + search.Length));
}
string abc = "AAAAX1";
if(abc.IndexOf("AA") == 0)
{
abc.Remove(0, 2);
abc = "XQ" + abc;
}

Categories

Resources