string manipulation check and replace with fastest method - c#

I have some strings like below:
string num1 = "D123_1";
string num2 = "D123_2";
string num3 = "D456_11";
string num4 = "D456_22";
string num5 = "D_123_D";
string num5 = "_D_123";
I want to make a function that will do the following actions:
1- Checks if given string DOES HAVE an Underscore in it, and this underscore should be after some Numbers and Follow with some numbers: in this case 'num5' and 'num6' are invalid!
2- Replace the numbers after the last underscore with any desired string, for example I want 'num1 = "D123_1"' to be changed into 'D123_2'
So far I came with this idea but it is not working :( First I dont know how to check for criteria 1 and second the replace statement is not working:
private string CheckAndReplace(string given, string toAdd)
{
var changedString = given.Split('_');
return changedString[changedString.Length - 1] + toAdd;
}
Any help and tips will be appriciated

What you are looking for is a regular expression. This is (mostly) from the top of my head. But it should easily point you in the right direction. The regular expression works fine.
public static Regex regex = new Regex("(?<character>[a-zA-Z]+)(?<major>\\d+)_(?<minor>\\d+)",RegexOptions.CultureInvariant | RegexOptions.Compiled);
Match m = regex.Match(InputText);
if (m.Succes)
{
var newValue = String.Format("{0}{1}_{2}"m.Groups["character"].Value, m.Groups["major"].Value, m.Groups["minor"].Value);
}

In your code you split the String into an array of strings and then access the wrong index of the array, so it isn't doing what you want.
Try working with a substring instead. Find the index of the last '_' and then get the substring:
private string CheckAndReplace(string given, string toAdd) {
int index = given.LastIndexOf('_')+1;
return given.Substring(0,index) + toAdd;
}
But before that check the validity of the string (see other answers). This code fragment will break when there's no '_' in the string.

You could use a regular expression (this is not a complete implementation, only a hint):
private string CheckAndReplace(string given, string toAdd)
{
Regex regex = new Regex("([A-Z]*[0-9]+_)[0-9]+");
if (regex.IsMatch(given))
{
return string.Concat(regex.Match(given).Groups[1].Value, toAdd);
}
else
{
... do something else
}
}

Use a good regular expression implementation. .NET has standard implementation of them

Related

Get substring between first occurance of "A" and last occurance of "B"

I have a string which has two tokens that bound a substring that I want to extract, but the substring may contain the tokens themselves, so I want between the 1st occurrence of token A and the last occurrence of token B. I also need to search for the tokens in a case-insensitive search.
Tried to wrap my head around using regex to get this, but can't seem to figure it out. Not sure the best approach here. String.split won't work.
I can't modify the casing of the data between the tokens in the string.
Try this, (I've made it into an extension method)
public static string Between(this string value, string a, string b)
{
int posA = value.IndexOf(a);
int posB = value.LastIndexOf(b);
if (posA == -1) || (posB == -1)
{
return "";
}
int adjustedPosA = posA + a.Length;
return (adjustedPosA >= posB) ? "" : value.Substring(adjustedPosA, posB - adjustedPosA);
}
Usage would be:
var myString = "hereIsAToken_andThisIsWhatIwant_andSomeOtherToken";
var whatINeed = myString.Between("hereIsAToken_", "_andSomeOtherToken");
An easy way to approach this problem is the use of the indexOf function provided by the string class. IndexOf returns the first occurence, lastIndexOf as the name suggests, the last one.
string data;
string token1;
string token2;
int start = data.IndexOf(token1)+token1.Length;
int end = data.LastIndexOf(token2);
string result = data.Substring(start, end-start);
From my personal point of view, regex might be a bit overkill here, just try my example :)

Replace a substring

I have an input string. I need to replace its prefix (until first dot) with an other string.
The method signature:
string MyPrefixReplace(string input, string replacer)
Examples:
string res = MyPrefixReplace("12.345.6789", "000")
res = "000.345.6789";
res = MyPrefixReplace("908.345.6789", "1")
res = "1.345.6789";
Is there a way not to extract a sub-string before first dot and make a Replace**?
I.e - I don't want this solution
int i = input.IndexOf(".");
string rep = input.Substring(0,i);
input.Replace(rep,replacer);
Thanks
You could use String.Split
public string MyPrefixReplace(string source, string value, char delimiter = '.')
{
var parts = source.Split(delimiter);
parts[0] = value;
return String.Join(delimiter.ToString(), parts);
}
Live demo
Using String.IndexOf and String.Substring ist the most efficient way. In your approach you have used the wrong overload of Substring. String.Replace is pointless anyway since you don't want to replace all occurences of the first part but only the first part.
Therefore you don't have to take but to skip the the first part and prefix another. This works as desired:
public static string MyPrefixReplace(string input, string replacer, char prefixChar = '.')
{
int index = input.IndexOf(prefixChar);
if (index == -1)
return input;
return replacer + input.Substring(index);
}
Your input:
string result = MyPrefixReplace("908.345.6789", "1"); // 1.345.6789
result = MyPrefixReplace("12.345.6789", "000"); // 000.345.6789
Personally, I'd split the string up to get around this problem, although there's obviously other ways of doing this, this would be my approach:
string Input = "123.456.789"
string[] SplitInput = Input.Split('.');
SplitInput[0] = "321";
string Output = String.Join('.', SplitInput);
Output should be "321.456.789".

Get exponential value using regular expression

I have string like this:
strings s = "1.0E-20"
Is there a way to get only -20 from this using regex?
I tried this:
(([1-9]+\.[0-9]*)|([1-9]*\.[0-9]+)|([1-9]+))([eE][-+]?[0-9]+)?
this gets me e-20 in group5 but still not just -20.
Use Regex for dealing with text, use Math(s) for dealing with numbers:
Math.Log10(Convert.ToDouble("1.0E-20")) // returns -20
To make sure your string input is a valid double use TryParse:
double d, result = 0.0;
if (Double.TryParse("1.0E-20", out d))
{
result = Math.Log10(d);
}
else
{
// handle error
}
Also, if you want to get the 1.0 (multiplier) from your input:
var d = Convert.ToDouble("1.0E-20");
var exponent = Math.Log10(d);
var multiplier = d / exponent;
No need for Regex when string methods can do wonders
string str = "1.0E-20";
str = str.Substring(str.IndexOf('E') + 1);
You can do that without Regex like:
string s = "1.0E-20";
string newStr = s.Substring(s.IndexOf('E') + 1);
Later you can parse the string to number like:
int number;
if (!int.TryParse(newStr, out number))
{
//invalid number
}
Console.WriteLine(number);
You can also use string.Split like:
string numberString = s.Split('E')[1]; //gives "-20"
Its better if you add check for string/array length when access string.Substring or accessing element 1 after split.
var x = str.IndexOf("E") != -1 ? str.Substring(str.IndexOf("E") + 1) : "1";
If you want to use regular expressions to achieve this, you should switch up your capture groups.
(([1-9]+\.[0-9]*)|([1-9]*\.[0-9]+)|([1-9]+))([eE])([-+]?[0-9]+)?
Group 6 will contain -20 with your given example with the regular expression above. Note how the parentheses have moved. We might need more information from you though. Do you have any more sample data? What's the end goal here?

Is there an easy way to trim the last three characters off a string

I have strings like this:
var a = "abcdefg";
var b = "xxxxxxxx";
The strings are always longer than five characters.
Now I need to trim off the last 3 characters. Is there some simple way that I can do this with C#?
In the trivial case you can just use
result = s.Substring(0, s.Length-3);
to remove the last three characters from the string.
Or as Jason suggested Remove is an alternative:
result = s.Remove(s.Length-3)
Unfortunately for unicode strings there can be a few problems:
A unicode codepoint can consist of multiple chars since the encoding of string is UTF-16 (See Surrogate pairs). This happens only for characters outside the basic plane, i.e. which have a code-point >2^16. This is relevant if you want to support Chinese.
A glyph (graphical symbol) can consist of multiple codepoints. For example ä can be written as a followed by a combining ¨.
Behavior with right-to-left writing might not be what you want either
You want String.Remove(Int32)
Deletes all the characters from this string beginning at a specified
position and continuing through the last position.
If you want to perform validation, along the lines of druttka's answer, I would suggest creating an extension method
public static class MyStringExtensions
{
public static string SafeRemove(this string s, int numCharactersToRemove)
{
if (numCharactersToRemove > s.Length)
{
throw new ArgumentException("numCharactersToRemove");
}
// other validation here
return s.Remove(s.Length - numCharactersToRemove);
}
}
var s = "123456";
var r = s.SafeRemove(3); //r = "123"
var t = s.SafeRemove(7); //throws ArgumentException
string a = "abcdefg";
a = a.Remove(a.Length - 3);
string newString = oldString.Substring(0, oldString.Length - 4);
If you really only need to trim off the last 3 characters, you can do this
string a = "abcdefg";
if (a.Length > 3)
{
a = a.Substring(0, a.Length-3);
}
else
{
a = String.Empty;
}

How to lowercase a string except for first character with C#

How do convert a string to lowercase except for the first character?
Can this be completed with LINQ?
Thanks
If you only have one word in the string, you can use TextInfo.ToTitleCase. No need to use Linq.
As #Guffa noted:
This will convert any string to title case, so, "hello world" and "HELLO WORLD" would both be converted to "Hello World".
To achieve exectly what you asked (convert all characters to lower, except the first one), you can do the following:
string mostLower = myString.Substring(0, 1) + myString.Substring(1).ToLower();
This can be done with simple string operations:
s = s.Substring(0, 1) + s.Substring(1).ToLower();
Note that this does exactly what you asked for, i.e. it converts all characters to lower case except the first one that is left unchanged.
If you instead also want to change the first character to upper case, you would do:
s = s.Substring(0, 1).ToUpper() + s.Substring(1).ToLower();
Note that this code assumes that there is at least two characters in the strings. If there is a possibility that it's shorter, you should of course test for that first.
String newString = new String(str.Select((ch, index) => (index == 0) ? ch : Char.ToLower(ch)).ToArray());
Use namespace: using System.Globalization;
...
string value = CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello");
EDIT
This code work only if its single word .For convert all character into lower except first letter check Guffa Answer.
string value = myString.Substring(0, 1) + myString.Substring(1).ToLower();
Not sure you can do it in linq here is a non-linq approach:
public static string FirstCap(string value)
{
string result = String.Empty;
if(!String.IsNullOrEmpty(value))
{
if(value.Length == 1)
{
result = value.ToUpper();
}
else
{
result = value.Substring(0,1).ToString().ToUpper() + value.Substring(1).ToLower();
}
}
return result;
}
based on guffa's example above (slightly amended). you could convert that to an extension method (please pardon the badly named method :)):
public static string UpperFirst(this string source)
{
return source.ToLower().Remove(0, 1)
.Insert(0, source.Substring(0, 1).ToUpper());
}
usage:
var myNewString = myOldString.UpperFirst();
// or simply referenced as myOldString.UpperFirst() where required
cheers guffa
var initialString = "Hello hOW r u?";
var res = string.Concat(initialString..ToUpper().Substring(0, 1), initialString.ToLower().Substring(1));
You can use an extension method:
static class StringExtensions
{
public static string ToLowerFirst(this string text)
=> !string.IsNullOrEmpty(text)
? $"{text.Substring(0, 1).ToLower()}{text.Substring(1)}"
: text;
}
Unit tests as well (using FluentAssertions and Microsoft UnitTesting):
[TestClass]
public class StringExtensionsTests
{
[TestMethod]
public void ToLowerFirst_ShouldReturnCorrectValue()
=> "ABCD"
.ToLowerFirst()
.Should()
.Be("aBCD");
[TestMethod]
public void ToLowerFirst_WhenStringIsEmpty_ShouldReturnCorrectValue()
=> string.Empty
.ToLowerFirst()
.Should()
.Be(string.Empty);
}

Categories