6

I am getting strings like "123456", "abcdef", "123abc" from another application. I need to format the strings like "123-456","abc-def", "123-abc". The length of the strings can also vary like we can have a string of lenght 30 char. If the 3rd position is chosen then after every 3rd character a hyphen should be inserted.

ex: input "abcdxy123z" output "abc-dxy-123-z" for 3rd position.

if we choose 2nd position then output will be

"ab-cd-xy-12-3z"

I tried with String.Format("{0:####-####-####-####}", Convert.ToInt64("1234567891234567")) but if I get a alphanumeric string, it does not work.

user2943892
  • 79
  • 1
  • 3

3 Answers3

9

You could use a little bit of Linq, like this:

string Hyphenate(string str, int pos) {
    return String.Join("-",
        str.Select((c, i) => new { c, i })
           .GroupBy(x => x.i / pos)
           .Select(g => String.Join("", g.Select(x => x.c))));
}

Or like this:

string Hyphenate(string str, int pos) {
    return String.Join("-",
        Enumerable.Range(0, (str.Length - 1) / pos + 1)
            .Select(i => str.Substring(i * pos, Math.Min(str.Length - i * pos, pos))));
}

Or you could use a regular expression, like this:

string Hyphenate(string str, int pos) {
    return String.Join("-", Regex.Split(str, @"(.{" + pos + "})")
                                 .Where(s => s.Length > 0));
}

Or like this:

string Hyphenate(string str, int pos) {
    return String.Join("-", Regex.Split(str, @"(?<=\G.{" + pos + "})(?!$)"));
}

All of these methods will return the same result:

Console.WriteLine(Hyphenate("abcdxy123z", 2)); // ab-cd-xy-12-3z
Console.WriteLine(Hyphenate("abcdxy123z", 3)); // abc-dxy-123-z
Console.WriteLine(Hyphenate("abcdxy123z", 4)); // abcd-xy12-3z
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
5

The power of the for statement:

string str = "12345667889";
int loc = 3;

for(int ins=loc; ins < str.Length; ins+=loc+1)
   str = str.Insert(ins,"-");

Gives 123-456-678-89

As a function:

string dashIt(string str,int loc)
{
  if (loc < 1) return str;

  StringBuilder work = new StringBuilder(str);

  for(int ins=loc; ins < work.Length; ins+=loc+1)
     work.Insert(ins,"-");

  return work.ToString();
}
Hogan
  • 69,564
  • 10
  • 76
  • 117
  • +1 for the second version, but your first code part uses `String.Insert` which returns _new_ string each call – Fedor Jan 29 '14 at 18:15
  • @Fyodor - true, the first one was done quickly to show how to do it with a for statement. As a side note, the Linq answers by p.s.w.g create as many or more strings as my first code example. – Hogan Jan 29 '14 at 19:27
  • Sure! I like it's brevity too, nice example, just noted that the second one is slightly different and get confused a little. – Fedor Jan 29 '14 at 19:46
  • @Fyodor - I could have used the same code as the first one in the 2nd example but the pass by reference vs pass by value issues would have made the code hard to understand for new coders... I felt this was clearer since it looked like what it did. – Hogan Jan 29 '14 at 20:42
3

With StringBuilder:

string input = "12345678"; //could be any length
int position = 3; //could be any other number
StringBuilder sb = new StringBuilder();

for (int i = 0; i < input.Length; i++)
{
    if (i % position == 0){
        sb.Append('-');
    }
    sb.Append(input[i]);
}
string formattedString = sb.ToString();
Zzyrk
  • 907
  • 8
  • 16