6
\$\begingroup\$

I have some underscore-delimited strings like abc_def_ghi. I would like to get a substring out of the string made of one or more delimited substrings, so that if I call:

getUnderscoreSubstring("abc_def_ghi",2)

then I get:

abc_def

This is the C# code I'm using:

public string getUnderscoreSubstring(string fullStr,int substringCount)
{
 string[] splitArray = fullStr.Split('_');
 if (substringCount>splitArray.Count())
 {
 return null;
 }
 else
 {
 string output = "";
 for(int c=0;c<substringCount;c++)
 {
 output += splitArray[c];
 if (c<substringCount-1)
 {
 output += "_";
 }
 }
 return output;
 }
}

I'm wondering if there's a simpler way to rewrite this, possibly using extension methods.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Apr 30, 2015 at 23:37
\$\endgroup\$
2
  • \$\begingroup\$ Please clarify your motivation. What do you want to be the result of getUnderscoreSubstring("__abc_def_ghi", 2), and why? \$\endgroup\$ Commented Apr 30, 2015 at 23:52
  • \$\begingroup\$ I don't have any values like that in the data set; they would be excluded from these function calls by prior validation. \$\endgroup\$ Commented Apr 30, 2015 at 23:57

2 Answers 2

8
\$\begingroup\$

Yes, you can definitely simplify this.

public string GetSubstring(string input, int count, char delimiter)
{
 return string.Join(delimiter.ToString(), 
 input.Split(delimiter).Take(count));
}

Calling it is as easy as GetSubstring(input, 2, '_')

What does it do?

  • Split the input string by the delimiter
  • Take the amount of substrings you want
  • Glue the selected substrings together with your delimiter

Very short and sexy!

This doesn't take the substringCount > splitArray.Count() in account but you can easily add that yourself: just split up the oneliner and add the appropriate check.


Now, some comments about your code:

  • Use .Length instead of .Count() when possible: the former will always be an O(1) operation, the latter sometimes an O(n). It won't make a difference here since an array implements ICollection<T> (and will use this optimization) but it's a good practice to observe.
  • Returning null is typically avoided for good reasons, consider an empty string or exception instead (don't go for the exception in this case).
  • I prefer to explicitly use string.Empty rather than an empty string to avoid confusion.
  • Write your variable names in full -- nobody is helped by abbreviating them.
  • Use a StringBuilder to concatenate in a loop to avoid unnecessary string object creating.
  • Leave some space in your code, it will read more fluently.
answered Apr 30, 2015 at 23:56
\$\endgroup\$
2
\$\begingroup\$

Basically, you want to find the substringCountth occurrence of '_' in the string, and return all the characters before that.

Basing on the code from https://stackoverflow.com/a/11363213/1108056

private int IndexOfNth(string str, char c, int n)
{
 int index = -1;
 while (n-- > 0)
 {
 index = str.IndexOf(c, index + 1);
 if (index == -1) break;
 }
 return index;
}
public string GetSubstring(string input, int count, char delimiter)
{
 return input.Substring(0,IndexOfNth(input, delimiter, count));
}
answered May 1, 2015 at 3:18
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.