1

I have a string of Hex numbers as, say

"010104000202000AC80627061202"

I want my output as

"01 01 04 00 02 02 00 0A C8 06 27 06 12 02"

I can use a for loop but is there any optimized way?

What I am doing currently is:

int length = line.Length/2; // Store the length of String
string outputstr = String.Empty;
for (int count = 0; count < length; count++)
  {
       outputstr += line.Substring(0, 2) + " "; //Get First two bytes and add space
       line = line.Substring(2); // Remove those two bytes
 }
7
  • 1
    Yes, use StringBuilder Commented Oct 31, 2013 at 12:50
  • 2
    Are you looking for faster or more elegant? Your method seems pretty easy to read. Commented Oct 31, 2013 at 12:52
  • I am looking for Faster way or as I said, "Optimized way" Commented Oct 31, 2013 at 12:56
  • @SwanandPurankar: Optimized does not necessarily mean faster. Performance is overrated. While users doesn't even notice a difference of few milliseconds they'll notice a bug(maybe caused by too complicated code) or an exceeded deadline for sure ;) Commented Oct 31, 2013 at 13:10
  • @TimSchmelter I agree with your statement that user will not notice the difference of miliseconds, But consider this (Assuming code is bug free) If it delays execution by 5 miliseconds and User executes code 100 times in a day, I can save him 500 mSec a day... 15 seconds a month... They cost a bomb for 15 seconds TV commercial, Think how important Every milisecond is!! ;) Commented Oct 31, 2013 at 13:29

7 Answers 7

4

You can use this regex:

string outputstr = Regex.Replace(inputstr, ".{2}", "$0 ");
Sign up to request clarification or add additional context in comments.

2 Comments

Regex are always elegant !
Small and elegant, but not performant. I think the OP asked for a performant way to do this.
2

This looks simple yet performing too.

private static string DoThat(string input)
{
    var sb = new StringBuilder(input.Length);
    for (int i = 0; i < input.Length; i += 2)
    {
        sb.Append(input, i, 2);
        sb.Append(" ");
    }
    return sb.ToString();
}

1 Comment

I'd rather construct the StringBuilder as follows: StringBuilder sb = new StringBuilder(Math.Max(0, line.Length * 3 / 2 - 1));, and use sb.Append(' ');. You also need if (sb.Length > 0) sb.Length--; at the end.
1

If you want faster you can change to stringbuilder:

int length = line.Length; // Store the length of String -- see edit below
StringBuilder output = new StringBuilder();
for (int count = 0; count < length; count += 2)  // makes more sense to increment the loop by 2
{
    output.Append(line.Substring(count, 2) + " "); //Get First two bytes and add space
}

One way to do it using Linq is

string.Join(" ",                      // join the string collection created below
    line.Select((c,i) => new {c,i})   // get each character and its index
        .GroupBy(g => g.i/2)          // group in pairs
        .Select(g => new string(g.Select(ci => ci.c).ToArray()))  // convert to char arrays and merge into strings
     );

Or

string.Join(" ",
Enumerable
    .Range(0, s.Length/2)
    .Select(i => s.Substring(i*2, 2))
 )

Although that essentially calls Substring in a "loop" so it may not be the most efficient method.

Comments

1

Because the length of your output string is known in advance, the fastest way is to allocate a char[] of the final size, fill it and then return new string(myCharBuffer);. This is also faster that the always praised StringBuilder. Just two allocations are needed, both of which have the perfect size, and the 2nd one is filled by memcpy.

7 Comments

Fill it means again for ??
Yes. If you want performance, that is what you need. Doesn't get faster than that. The more abstractions you add, the slower it gets. This is the fastest method I know of (that's safe managed code).
What makes you think that StringBuilder would be slower, if constructed with the correct length?
@KrisVandermotten because it can't possibly as fast as sequentially setting a few bytes in an array. It does more stuff. Also, care must be taken not to call Substring in the inner loop and pass substrings to StringBuilder. That would destroy performance.
Ah, but that's the thing, what Append is doing, is exactly that: setting a few bytes in an array and keeping track of where you are in that array (which is something you would have to do as well). For long strings this algorithm will be bound by memory speeds, and both will be equally fast. For short strings it won't matter. As for the Substring: of course, but that applies to both cases. See the answer by Sriram Sakthivel and my comment there.
|
1

Firstly, if you are going to loop and use string manipulation, use a Stringbuilder.

This is because a String is immutable, and while it may seem as if you are altering it, a new object is actually created each iteration and is kept in the stack.

Comments

1

You could use a StringBuilder if the string is large:

if(line.Length > 100)
{
    StringBuilder sb = new StringBuilder(line.Length + line.Length/2);
    for(int i=0; i < line.Length; i++)
    {
        sb.Append(line[i]);
        if (i % 2 == 1 && i < line.Length-1)
            sb.Append(' ');
    }
    return sb.ToString();
}
// else your approach

Comments

0

You could something like this:

var unformatedString = "010104000202000AC80627061202";
var formatedString = Regex.Replace(@"..", "$0 ");

This is definitely not faster, but alot easier to read.

Comments

Your Answer

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.