Related
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]
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]
I'm looking for String extension methods for TrimStart() and TrimEnd() that accept a string parameter.
I could build one myself but I'm always interested in seeing how other people do things.
How can this be done?
To trim all occurrences of the (exactly matching) string, you can use something like the following:
TrimStart
public static string TrimStart(this string target, string trimString)
{
if (string.IsNullOrEmpty(trimString)) return target;
string result = target;
while (result.StartsWith(trimString))
{
result = result.Substring(trimString.Length);
}
return result;
}
TrimEnd
public static string TrimEnd(this string target, string trimString)
{
if (string.IsNullOrEmpty(trimString)) return target;
string result = target;
while (result.EndsWith(trimString))
{
result = result.Substring(0, result.Length - trimString.Length);
}
return result;
}
To trim any of the characters in trimChars from the start/end of target (e.g. "foobar'#"#';".TrimEnd(";#'") will return "foobar") you can use the following:
TrimStart
public static string TrimStart(this string target, string trimChars)
{
return target.TrimStart(trimChars.ToCharArray());
}
TrimEnd
public static string TrimEnd(this string target, string trimChars)
{
return target.TrimEnd(trimChars.ToCharArray());
}
TrimStart and TrimEnd takes in an array of chars. This means that you can pass in a string as a char array like this:
var trimChars = " .+-";
var trimmed = myString.TrimStart(trimChars.ToCharArray());
So I don't see the need for an overload that takes a string parameter.
I thought the question was trying to trim a specific string from the start of a larger string.
For instance, if I had the string "hellohellogoodbyehello", if you tried to call TrimStart("hello") you would get back "goodbyehello".
If that is the case, you could use code like the following:
string TrimStart(string source, string toTrim)
{
string s = source;
while (s.StartsWith(toTrim))
{
s = s.Substring(toTrim.Length - 1);
}
return s;
}
This wouldn't be super-efficient if you needed to do a lot of string-trimming, but if its just for a few cases, it is simple and gets the job done.
To match entire string and not allocate multiple substrings, you should use the following:
public static string TrimStart(this string source, string value, StringComparison comparisonType)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
int valueLength = value.Length;
int startIndex = 0;
while (source.IndexOf(value, startIndex, comparisonType) == startIndex)
{
startIndex += valueLength;
}
return source.Substring(startIndex);
}
public static string TrimEnd(this string source, string value, StringComparison comparisonType)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
int sourceLength = source.Length;
int valueLength = value.Length;
int count = sourceLength;
while (source.LastIndexOf(value, count, comparisonType) == count - valueLength)
{
count -= valueLength;
}
return source.Substring(0, count);
}
from dotnetperls.com,
Performance
Unfortunately, the TrimStart method is not heavily optimized. In
specific situations, you will likely be able to write character-based
iteration code that can outperform it. This is because an array must
be created to use TrimStart.
However: Custom code would not necessarily require an array. But for
quickly-developed applications, the TrimStart method is useful.
There is no built in function in C# - but you can write your own extension methods which I will show you below - they can be used like the builtin ones to trim characters, but here you can use strings to trim.
Note that with IndexOf / LastIndexOf, you can choose if it is case sensitive / culture sensitive or not.
I have implemented the feature "repetitive trims" as well (see the optional parameters).
Usage:
// myStr: the string that needs to be trimmed
// trimStr: the string to trim from myStr
var trimmed1 = myStr.TrimStart(trimStr);
var trimmed2 = myStr.TrimEnd(trimStr);
var trimmed3 = myStr.TrimStr(trimStr);
var trimmed4 = myStr.Trim(trimStr);
There is one function TrimStr(..) trimming from the start and from the end of the string, plus three functions implementing .TrimStart(...), .TrimEnd(...) and .Trim(..) for compatibility with the .NET trims:
Try it in DotNetFiddle
public static class Extension
{
public static string TrimStr(this string str, string trimStr,
bool trimEnd = true, bool repeatTrim = true,
StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
{
int strLen;
do
{
strLen = str.Length;
{
if (trimEnd)
{
if (!(str ?? "").EndsWith(trimStr)) return str;
var pos = str.LastIndexOf(trimStr, comparisonType);
if ((!(pos >= 0)) || (!(str.Length - trimStr.Length == pos))) break;
str = str.Substring(0, pos);
}
else
{
if (!(str ?? "").StartsWith(trimStr)) return str;
var pos = str.IndexOf(trimStr, comparisonType);
if (!(pos == 0)) break;
str = str.Substring(trimStr.Length, str.Length - trimStr.Length);
}
}
} while (repeatTrim && strLen > str.Length);
return str;
}
// the following is C#6 syntax, if you're not using C#6 yet
// replace "=> ..." by { return ... }
public static string TrimEnd(this string str, string trimStr,
bool repeatTrim = true,
StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
=> TrimStr(str, trimStr, true, repeatTrim, comparisonType);
public static string TrimStart(this string str, string trimStr,
bool repeatTrim = true,
StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
=> TrimStr(str, trimStr, false, repeatTrim, comparisonType);
public static string Trim(this string str, string trimStr, bool repeatTrim = true,
StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
=> str.TrimStart(trimStr, repeatTrim, comparisonType)
.TrimEnd(trimStr, repeatTrim, comparisonType);
}
Now you can just use it like
Console.WriteLine("Sammy".TrimEnd("my"));
Console.WriteLine("Sammy".TrimStart("Sam"));
Console.WriteLine("moinmoin gibts gips? gips gibts moin".TrimStart("moin", false));
Console.WriteLine("moinmoin gibts gips? gips gibts moin".Trim("moin").Trim());
which creates the output
Sam
my
moin gibts gips? gips gibts moin
gibts gips? gips gibts
In the last example, the trim function does a repetitive trim, trimming all occurances of "moin" at the beginning and at the end of the string. The example before just trims "moin" only once from the start.
I'm assuming you mean that, for example, given the string "HelloWorld" and calling the function to 'trim' the start with "Hello" you'd be left with "World". I'd argue that this is really a substring operation as you're removing a portion of the string of known length, rather than a trim operation which removes an unknown length of string.
As such, we created a couple of extension methods named SubstringAfter and SubstringBefore. It would be nice to have them in the framework, but they aren't so you need to implement them yourselves. Don't forget to have a StringComparison parameter, and to use Ordinal as the default if you make it optional.
If you did want one that didn't use the built in trim functions for whatever reasons, assuming you want an input string to use for trimming such as " ~!" to essentially be the same as the built in TrimStart with [' ', '~', '!']
public static String TrimStart(this string inp, string chars)
{
while(chars.Contains(inp[0]))
{
inp = inp.Substring(1);
}
return inp;
}
public static String TrimEnd(this string inp, string chars)
{
while (chars.Contains(inp[inp.Length-1]))
{
inp = inp.Substring(0, inp.Length-1);
}
return inp;
}
Function to trim start/end of a string with a string parameter, but only once (no looping, this single case is more popular, loop can be added with an extra param to trigger it) :
public static class BasicStringExtensions
{
public static string TrimStartString(this string str, string trimValue)
{
if (str.StartsWith(trimValue))
return str.TrimStart(trimValue.ToCharArray());
//otherwise don't modify
return str;
}
public static string TrimEndString(this string str, string trimValue)
{
if (str.EndsWith(trimValue))
return str.TrimEnd(trimValue.ToCharArray());
//otherwise don't modify
return str;
}
}
As mentioned before, if you want to implement the "while loop" approach, be sure to check for empty string otherwise it can loop forever.
How effectively remove all character in string that placed before character "."?
Input:
Amerika.USA
Output:
USA
You can use the IndexOf method and the Substring method like so:
string output = input.Substring(input.IndexOf('.') + 1);
The above doesn't have error handling, so if a period doesn't exist in the input string, it will present problems.
You could try this:
string input = "lala.bla";
output = input.Split('.').Last();
string input = "America.USA"
string output = input.Substring(input.IndexOf('.') + 1);
String input = ....;
int index = input.IndexOf('.');
if(index >= 0)
{
return input.Substring(index + 1);
}
This will return the new word.
Extension methods I commonly use to solve this problem:
public static string RemoveAfter(this string value, string character)
{
int index = value.IndexOf(character);
if (index > 0)
{
value = value.Substring(0, index);
}
return value;
}
public static string RemoveBefore(this string value, string character)
{
int index = value.IndexOf(character);
if (index > 0)
{
value = value.Substring(index + 1);
}
return value;
}
public string RemoveCharactersBeforeDot(string s)
{
string splitted=s.Split('.');
return splitted[splitted.Length-1]
}
A couple of methods that, if the char does not exists, return the original string.
This one cuts the string after the first occurrence of the pivot:
public static string truncateStringAfterChar(string input, char pivot){
int index = input.IndexOf(pivot);
if(index >= 0) {
return input.Substring(index + 1);
}
return input;
}
This one instead cuts the string after the last occurrence of the pivot:
public static string truncateStringAfterLastChar(string input, char pivot){
return input.Split(pivot).Last();
}
How can I extract a substring which is composed of the rightmost six letters from another string?
Ex: my string is "PER 343573". Now I want to extract only "343573".
How can I do this?
string SubString = MyString.Substring(MyString.Length-6);
Write an extension method to express the Right(n); function. The function should deal with null or empty strings returning an empty string, strings shorter than the max length returning the original string and strings longer than the max length returning the max length of rightmost characters.
public static string Right(this string sValue, int iMaxLength)
{
//Check if the value is valid
if (string.IsNullOrEmpty(sValue))
{
//Set valid empty string as string could be null
sValue = string.Empty;
}
else if (sValue.Length > iMaxLength)
{
//Make the string no longer than the max length
sValue = sValue.Substring(sValue.Length - iMaxLength, iMaxLength);
}
//Return the string
return sValue;
}
Probably nicer to use an extension method:
public static class StringExtensions
{
public static string Right(this string str, int length)
{
return str.Substring(str.Length - length, length);
}
}
Usage
string myStr = "PER 343573";
string subStr = myStr.Right(6);
using System;
public static class DataTypeExtensions
{
#region Methods
public static string Left(this string str, int length)
{
str = (str ?? string.Empty);
return str.Substring(0, Math.Min(length, str.Length));
}
public static string Right(this string str, int length)
{
str = (str ?? string.Empty);
return (str.Length >= length)
? str.Substring(str.Length - length, length)
: str;
}
#endregion
}
Shouldn't error, returns nulls as empty string, returns trimmed or base values. Use it like "testx".Left(4) or str.Right(12);
MSDN
String mystr = "PER 343573";
String number = mystr.Substring(mystr.Length-6);
EDIT: too slow...
if you are not sure of the length of your string, but you are sure of the words count (always 2 words in this case, like 'xxx yyyyyy') you'd better use split.
string Result = "PER 343573".Split(" ")[1];
this always returns the second word of your string.
This isn't exactly what you are asking for, but just looking at the example, it appears that you are looking for the numeric section of the string.
If this is always the case, then a good way to do it would be using a regular expression.
var regex= new Regex("\n+");
string numberString = regex.Match(page).Value;
Since you are using .NET, which all compiles to MSIL, just reference Microsoft.VisualBasic, and use Microsoft's built-in Strings.Right method:
using Microsoft.VisualBasic;
...
string input = "PER 343573";
string output = Strings.Right(input, 6);
No need to create a custom extension method or other work. The result is achieved with one reference and one simple line of code.
As further info on this, using Visual Basic methods with C# has been documented elsewhere. I personally stumbled on it first when trying to parse a file, and found this SO thread on using the Microsoft.VisualBasic.FileIO.TextFieldParser class to be extremely useful for parsing .csv files.
Use this:
String text = "PER 343573";
String numbers = text;
if (text.Length > 6)
{
numbers = text.Substring(text.Length - 6);
}
Guessing at your requirements but the following regular expression will yield only on 6 alphanumerics before the end of the string and no match otherwise.
string result = Regex.Match("PER 343573", #"[a-zA-Z\d]{6}$").Value;
var str = "PER 343573";
var right6 = string.IsNullOrWhiteSpace(str) ? string.Empty
: str.Length < 6 ? str
: str.Substring(str.Length - 6); // "343573"
// alternative
var alt_right6 = new string(str.Reverse().Take(6).Reverse().ToArray()); // "343573"
this supports any number of character in the str. the alternative code not support null string. and, the first is faster and the second is more compact.
i prefer the second one if knowing the str containing short string. if it's long string the first one is more suitable.
e.g.
var str = "";
var right6 = string.IsNullOrWhiteSpace(str) ? string.Empty
: str.Length < 6 ? str
: str.Substring(str.Length - 6); // ""
// alternative
var alt_right6 = new string(str.Reverse().Take(6).Reverse().ToArray()); // ""
or
var str = "123";
var right6 = string.IsNullOrWhiteSpace(str) ? string.Empty
: str.Length < 6 ? str
: str.Substring(str.Length - 6); // "123"
// alternative
var alt_right6 = new string(str.Reverse().Take(6).Reverse().ToArray()); // "123"
Another solution that may not be mentioned
S.Substring(S.Length < 6 ? 0 : S.Length - 6)
Use this:
string mystr = "PER 343573";
int number = Convert.ToInt32(mystr.Replace("PER ",""));
Null Safe Methods :
Strings shorter than the max length returning the original string
String Right Extension Method
public static string Right(this string input, int count) =>
String.Join("", (input + "").ToCharArray().Reverse().Take(count).Reverse());
String Left Extension Method
public static string Left(this string input, int count) =>
String.Join("", (input + "").ToCharArray().Take(count));
Here's the solution I use...
It checks that the input string's length isn't lower than the asked length. The solutions I see posted above don't take this into account unfortunately - which can lead to crashes.
/// <summary>
/// Gets the last x-<paramref name="amount"/> of characters from the given string.
/// If the given string's length is smaller than the requested <see cref="amount"/> the full string is returned.
/// If the given <paramref name="amount"/> is negative, an empty string will be returned.
/// </summary>
/// <param name="string">The string from which to extract the last x-<paramref name="amount"/> of characters.</param>
/// <param name="amount">The amount of characters to return.</param>
/// <returns>The last x-<paramref name="amount"/> of characters from the given string.</returns>
public static string GetLast(this string #string, int amount)
{
if (#string == null) {
return #string;
}
if (amount < 0) {
return String.Empty;
}
if (amount >= #string.Length) {
return #string;
} else {
return #string.Substring(#string.Length - amount);
}
}
This is the method I use: I like to keep things simple.
private string TakeLast(string input, int num)
{
if (num > input.Length)
{
num = input.Length;
}
return input.Substring(input.Length - num);
}
//s - your string
//n - maximum number of right characters to take at the end of string
(new Regex("^.*?(.{1,n})$")).Replace(s,"$1")
Just a thought:
public static string Right(this string #this, int length) {
return #this.Substring(Math.Max(#this.Length - length, 0));
}
Without resorting to the bit converter and bit shifting (need to be sure of encoding)
this is fastest method I use as an extension method 'Right'.
string myString = "123456789123456789";
if (myString > 6)
{
char[] cString = myString.ToCharArray();
Array.Reverse(myString);
Array.Resize(ref myString, 6);
Array.Reverse(myString);
string val = new string(myString);
}
I use the Min to prevent the negative situations and also handle null strings
// <summary>
/// Returns a string containing a specified number of characters from the right side of a string.
/// </summary>
public static string Right(this string value, int length)
{
string result = value;
if (value != null)
result = value.Substring(0, Math.Min(value.Length, length));
return result;
}
using Microsoft.visualBasic;
public class test{
public void main(){
string randomString = "Random Word";
print (Strings.right(randomString,4));
}
}
output is "Word"
//Last word of string :: -> sentence
var str ="A random sentence";
var lword = str.Substring(str.LastIndexOf(' ') + 1);
//Last 6 chars of string :: -> ntence
var n = 6;
var right = str.Length >n ? str.Substring(str.Length - n) : "";