Reputation:
I have a method that extracts a username from a string using conditionals to check common conventions, although it is resulting in an ArgumentOutOfRangeException
on the GetPart
utility method, even after explicitly checking before calling it?
Here is the extraction method
public bool TryExtractUsernameFromString(string str, out string username)
{
if (str.Contains("un: "))
{
username = GetPart(str, "un: ", " ");
}
else if (str.Contains("un:"))
{
username = str.Split(" ").Where(x => x.StartsWith("un:")).First().Substring(3);
}
else if (str.Contains("un- "))
{
username = str.IndexOf(" ", str.IndexOf("un- ") + 1) > 0 ? GetPart(str, "un- ", " ") : str[str.IndexOf("un- ")..str.Length];
}
else if (str.Contains("un-"))
{
username = str.Split(" ").Where(x => x.StartsWith("un-")).First().Substring(3);
}
else
{
username = "";
}
return username.Length > 0;
}
I am passing this as the first argument to TryExtractUsernameFromString
(without quotes)
"😊un- jennyfromtheblock"
So it happens here,
else if (str.Contains("un- "))
{
username = str.IndexOf(" ", (str.IndexOf("un- ") + 1)) > 0 ? GetPart(str, "un- ", " ") : str[str.IndexOf("un -")..str.Length];
}
But shouldn't be calling GetPart()
if it doesn't contain a second space after the first one in the str.Contains
check.
GetPart method:
public static string GetPart(string s, string start, string end)
{
return s[(s.IndexOf(start) + start.Length)..s.IndexOf(end)];
}
Upvotes: 0
Views: 81
Reputation: 5140
@DanRayson looks correct; But I wanted to add there is likely a much cleaner approach to this.
If statements can suck, case statements aren't really better. If you assume any name could have 0 or more matches:
public static void CleanName(string nameString, List<string> badPrefixes)
{
var matchedPrefixes = badPrefixes.Where(w => nameString.Contains(w)
&& && nameString.IndexOf(w) == 0).ToList();
foreach(var prefix in matchedPrefixes)
{
Console.WriteLine(nameString.Replace(prefix, "").Trim());
}
if (!matchedPrefixes.Any())
{
Console.WriteLine(nameString);
}
}
Another option would be using .FirstOrDefault
instead of selecting all of the matches. But essentially, just find the match(es) and then remove it, and finally trim spaces.
public static void Main()
{
List<string> badPrefixes = new List<string>()
{
"un:",
"un-",
"un ",
"Un", //Fun example too
};
string longUserName1 = "un- Austin";
string riskyLongName = "un: theUndying";
CleanName(longUserName1, badPrefixes);
// output: Austin
CleanName(riskyLongName, badPrefixes);
// output: theUndying
}
Upvotes: 0
Reputation: 1437
str.IndexOf("un- ") + 1
is returning the index of the START + 1 of that substring. Try using str.IndexOf("un- ") + 4
instead. That'll get you the index of the second space you're looking for.
Upvotes: 2