2 days ago, there was a question related to string.LastIndexOf(String.Empty) returning the last index of string:
Do C# strings end with empty string?
So I thought that; a string can always contain string.empty between characters like:
"testing" == "t" + String.Empty + "e" + String.Empty +"sting" + String.Empty;
After this, I wanted to test if String.IndexOf(String.Empty) was returning 0 because since String.Empty can be between any char in a string, that would be what I expect it to return and I wasn't wrong.
string testString = "testing";
int index = testString.LastIndexOf(string.Empty); // index is 6
index = testString.IndexOf(string.Empty); // index is 0
It actually returned 0. I started to think that if I could split a string with String.Empty, I would get at least 2 string and those would be String.Empty and rest of the string since String.IndexOf(String.Empty) returned 0 and String.LastIndexOf(String.Empty) returned length of the string.. Here is what I coded:
string emptyString = string.Empty;
char[] emptyStringCharArr = emptyString.ToCharArray();
string myDummyString = "abcdefg";
string[] result = myDummyString.Split(emptyStringCharArr);
The problem here is, I can't obviously convert String.Empty to char[] and result in an empty string[]. I would really love to see the result of this operation and the reason behind this. So my questions are:
Is there any way to split a string with String.Empty?
If it is not possible but in an absolute world which it would be possible, would it return an array full of chars like [0] = "t" [1] = "e" [2] = "s" and so on or would it just return the complete string? Which would make more sense and why?
Yes, you can split any string with string .Empty
string[] strArr = s.Split(string.Empty.ToCharArray());
You will always get an Index of 0 when you look for String.Empty in any String, because it's the definition of String.IndexOf(String.Empty) you should have a look at the MSDN, where it says:
"The zero-based index position of
value if that string is found, or -1
if it is not. If value is
String.Empty, the return value is 0."
Directed to your second Question:
I think you can Split a String with an Empty String by doing something like this in your code:
String test = "fwewfeoj";
test.Split(new String[] { String.Empty }, StringSplitOptions.None);
By the way: Possible Clone of this answer
Why does "abcd".StartsWith("") return true?
Do you really need to split the string, or are you just trying to get all the individual characters?
If so, then a string is also a IEnumerable<char>, and you also have an indexer.
So, what are you actually trying to do?
And no, you can't call the split methods with string.Empty or similar constructs.
string emptyString = string.Empty;
char[] emptyStringCharArr = emptyString.ToCharArray();
This will give you an empty array of chars.
This is because String is already an array of chars in memory, and String.Empty has no value.
To break it down further, consider an implementation of .ToCharArray()
private Char[] toCharArray(String value)
{
var stringLength = value.Length;
var returningArray = new char[stringLength];
for(var i = 0; i < stringLength; i++)
{
returningArray[i] = value[i];
}
return returningArray;
}
Length of course will be zero, and you will return an empty char array. Of course this isn't the exact implementation, but you can see how and why it's returning nothing (and therefore isn't splitting on the string as you're expecting it to)
It's not an array with a single element String.Empty, because that doesn't really make sense. When you try to split on an empty array, it doesn't know how or what to split on, so you're given back the original string.
As for why it returns 0 by default, consider:
private int IndexOf(String value, String searchFor)
{
for(var i = 0; i < value.Length; i++)
{
if(value.Substring(i, searchFor.Length) == searchFor)
{
return i;
}
}
return -1;
}
private int LastIndexOf(String value, String searchFor)
{
var searchLength = searchFor.Length;
for(var i = value.Length - searchFor.Length; i >= 0; i--)
{
if(value.Substring(i, searchLength) == searchFor)
return i;
}
return -1;
}
String.SubString(x, 0) will ALWAYS return String.Empty, regardless of what's passed in (even String.Empty). For this reason it's much faster to add a check and return 0 regardless (as it would even if it ran the loop).
Since String.Empty is just an empty string, so if you do:
var s = "part1" + string.Empty + "part2";
this will result in exactly the same string as:
var s = "part1" + "part2";
the first syntax will not insert a magic empty string between the two parts.
That IndexOf returns 0, is by definition, not because there is some magic empty string between characters.
I cannot think of a logic way to split a string, by an empty string. What should it return? When using an empty string as an argument to the string.Split method, it will be ignored. If it was the only separator to use, the string will be returned unsplit.
you could also say
"testing" == string.Empty + string.Empty + string.Empty + ... + "t" + string.Empty + string.empty + "esting";
So actually you could place an endless array of string.empty between each character.
So I think
1 not possible
2 none, it just doens't make sense...
Related
So we have ?? to parse its right-hand value for when the left hand is null.
What is the equivalent for a string[].
For example
string value = "One - Two"
string firstValue = value.Split('-')[0] ?? string.Empty;
string secondValue = value.Split('-')[1] ?? string.Empty;
Above example would still crash if we would try to get a third index or if string value = "One". Because it is not null but IndexOutOfRangeException is thrown.
https://learn.microsoft.com/en-us/dotnet/api/system.indexoutofrangeexception
So what is a one-line solution to tackle the above problem? I'd like to avoid the try-catch scenario because this gives ugly code.
I want to get value out of a string[] with a string.Empty as a backup value so my string is never null.
Well, you can try Linq:
using System.Linq;
...
string thirdValue = value.Split('-').ElementAtOrDefault(2) ?? string.Empty;
However, your code has a drawback: you constantly Split the same string. I suggest extracting value.Split('-'):
string value = "One - Two"
var items = value.Split('-');
string firstValue = items.ElementAtOrDefault(0) ?? string.Empty;
string secondValue = items.ElementAtOrDefault(1) ?? string.Empty;
I suggest you create a method for this. which will accept two inputs of type string(representing the input string) and an integer(represents the specified index), and should return the split value if the specified index is available, else it will return an empty string:
string GetSubstring(string input, int index)
{
string returnValue = String.Empty;
string[] substrings = input.Split(new[] { "-" }, StringSplitOptions.RemoveEmptyEntries);
returnValue = substrings.Length > index ? substrings[index] : returnValue;
return returnValue;
}
Here is a working example for your reference
One way to achieve this is to use MoreLinq's Lead and tuple destructuring:
string value = "One - Two";
var (first, second) = value.Split('-').Lead(1, string.Empty, (x, y) => (x, y)).First();
Or, if you want a more generic approach that works for all indices:
string value = "One - Two - Three - Fourth - Fifth";
var (first, second) = value.Split('-').Skip(6).Concat(string.Empty).Lead(7, string.Empty, (x, y) => (x, y)).First();
This code will get the seventh and fourteenth entries (neither of which are there, so string.Empty will be used for both).
Another option to consider is to assign two different variables on the same line of code:
string value = "One - Two";
var split = value.Split('-');
string first = split[0] ?? string.Empty, second = split.ElementAtOrDefault(1) ?? string.Empty;
This gives you three lines of code, good performance and reasonable level of clarity and readability.
Note there is no need to use ElementOrDefault(0) - better to use [0] since Split will never return an array with no elements in it.
Another option would be to use destructuring - but that is really only useful if you are interested in contiguous entries at the start of the array (although it could be tweaked to take index parameters reasonably simply):
public static void Destructure<T>(this T[] items, T defaultValue, out T t0, out T t1)
{
t0 = items.Length > 0 ? items[0] : defaultValue;
t1 = items.Length > 1 ? items[1] : defaultValue;
}
Maybe the following code will be useful
string value = "One - Two";
string firstValue = (value.Split('-').Length == 1 ? value.Split('-')[0] : null) ?? string.Empty;
string secondValue = (value.Split('-').Length == 2 ? value.Split('-')[1] : null) ?? string.Empty;
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 :)
This question already has answers here:
How would you count occurrences of a string (actually a char) within a string?
(34 answers)
Closed 8 years ago.
Is there a method to get the number of replacements using .Replace("a", "A"); ?
Example:
String string_1 = "a a a";
String string_2 = string_1.Replace("a", "A");
In this case, the output should be 3, because a was replaced with A 3 times.
You can get the count using .Split function :
string_1.Split(new string[] { "a" }, StringSplitOptions.None).Length-1;
After splitting the string we will get one item more. Because, .Split function returns a string array that contains the substrings in this string that are delimited by elements of a specified string array. So, the Length property's value will be n+1.
You cannot do this directly with string.Replace, but you could use the string.IndexOf to search for your string until it doesn't find a match
int counter = 0;
int startIndex = -1;
string string_1 = "a a a";
while((startIndex = (string_1.IndexOf("a", startIndex + 1))) != -1)
counter++;
Console.WriteLine(counter);
If this becomes of frequent use then you could plan to create an extension method
public static class StringExtensions
{
public static int CountMatches(this string source, string searchText)
{
if(string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(searchText))
return 0;
int counter = 0;
int startIndex = -1;
while((startIndex = (source.IndexOf(searchText, startIndex + 1))) != -1)
counter++;
return counter;
}
}
and call it with
int count = string_1.CountMatches("a");
The advantages of IndexOf are in the fact that you don't need to create an array of strings (Split) or an array of objects (Regex.Matches). It is just a plain vanilla loop involving integers.
You can use the Regex.Matches method to find out what would be replaced. Use the Regex.Escape method to escape the string if it would contain any characters that would be treated specially as a regular expression.
int cnt = Regex.Matches(string_1, Regex.Escape("a")).Count;
Just like the title says.
I've tried doing str.Replace("","0"); but it gave me error because oldValue has zero length.
Is it possible to replace string.Empty into something?
Edit:
I am maintaining a program and I encountered that the program was calling a method that'll return a string then be converted to Int32.
int x = Convert.toInt32(Method1());
public string Method1()
{
string retString = string.Empty;
//Do Something
return retString
}
You can simply return "0" for null, zero length or whitespace string using this one-liner:
return String.IsNullOrWhiteSpace(str) ? "0" : str;
String.Replace takes two string arguments oldValue and newValue. You specified the newValue 0 however an empty string is not legal for the oldValue.
try below code :-
str.Replace(" ","0");
or you can just assign "0" to emptry string as below :-
if(str == string.Empty)
{
str = "0";
}
or making it simple :-
String.IsNullOrWhiteSpace(str) ? "0" : str;
You can't replace empty string within the string, but you can replace, say, spaces, e.g.
str = str.Replace(" ", "0"); // providing str is not null
Or you can substitute empty string with "0":
if (String.IsNullOrEmpty(str))
str = "0";
When parsing string into int you can do something like that:
int x = String.IsNullOrEmpty(str) ? 0 : Convert.ToInt32(str);
In method() you can do:
return String.IsNullOrEmpty(retString) ? "0" : retString;
If you want to check if the value is empty and then set the value to zero, otherwise use the default value you can use an inline if like so:
return string.IsNullOrWhiteSpace(retString ) ? "0" : retString;
If you know that str is empty then you may use star="a"
If you want to check then write statement in if condition.
After your edit:
To convert an empty string to 0, and parse a non-empty string as an integer, I wouldn't deal with a "0" at all, but combine the two in a single method. For example:
int Parse(string s, int d = 0) {
if (string.IsNullOrEmpty(s))
return d;
return int.Parse(s);
}
Try This...
public string Method1()
{
string retString = string.Empty;
//Do Something
return string.IsNullOrEmpty(retString)?"0":retString;
}
It is not possible to replace string.Empty by "0". It will throw ArgumentException.
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll.
Additional information: String cannot be of zero length.
You can try following code:
if(retString == string.Empty)
{
retString = "0";
}
It sounds like your best option would be int.TryParse, if you encounter a string that can't be set to a valid value, it will set it to the default value for an integer (0) as well as returning a boolean so you can know this has happened.
int myInt;
if(!int.TryParse(myStringVariable, out myInt))
{
//Invalid integer you can put something here if you like but not needed
//myInt has been set to zero
}
//The same code without the if statement, still sets myInt
int.TryParse(myStringVariable, out myInt);
I'm trying to compare first 3 chars of a string, i'm trying to use substring then compare.
The strings are read from an input file, and the string may not be 3 chars long. if an string is not 3 chars long i want the substring method to replace the empty chars with spaces.
How would i go about doing that.
Current code throws an exeption when the string is not long enough.
Use String.PadRight
myString.PadRight(3, ' ');
// do SubString here..
You could also create a .Left extension method that doesn't throw an exception when the string isn't big enough:
public static string Left(this string s, int len)
{
if (len == 0 || s.Length == 0)
return "";
else if (s.Length <= len)
return s;
else
return s.Substring(0, len);
}
Usage:
myString.Left(3);
Use one of the String.PadRight() methods before calling Substring():
string subString = myString.PadRight(3).Substring(0,3);
If you use the overload with one parameter like I did above, it will insert spaces.
string subString1 = string1.PadRight(3).Substring(0,3);
string subString2 = string2.PadRight(3).Substring(0,3);
if (String.Compare(subString1, subString2) == 0)
{
// if equal
}
else
{
// not equal
}
I used separate variables because it's a bit more readable, but you could in-line them in the if statement if you wanted to.
You can use this dirty hack:
var res = (myStr+" ").Substring(...);