Help on string

  • Thread starter Thread starter SnakeS
  • Start date Start date
S

SnakeS

Hi,

I want modify a string as "112233445566" in
"11:22:33:44:55:66"

which is the best method?

Using a RegExp? and if yes how?

Thanks in advance
 
Hi,

Does the string has the same length always?
what is the criteria for include the ":"
From the answers to these question depends the solutions.

if you always want to split in two continuos chars you could do something
like this

StringBuilder sb = new StringBuilder()
int start = 0;
string str = "112233445566";
while ( str.Length - start > 2 )
{
if ( sb.Length == 0 )
sb.Append( str.substring( start, 2 ) );
else
{
sb.Append( ":" );
sb.Append( str.substring( start, 2 ) );
}
start +=2;
}


This may give you some ideas, just notice that I wrote the text here and it
may have errors

Cheers,
 
C Addison Ritchie said:
This seems to work well.

using System.Text;
using System.Text.RegularExpressions;

// your string "112233445566";
string s = "112233445566";

// create the regular expression
Regex re = new Regex("(\\d\\d)");

// find the matches
MatchCollection matches = re.Matches();

// build the string
string result = String.Format("{0}:{1}:{2}:{3}:{4}:{5}",
matches[0].Value,
matches[1].Value,
matches[2].Value,
matches[3].Value,
matches[4].Value,
matches[5].Value);

return result;

The input string must be 12 characters long and all numbers. I would
assert that this is true before executing the above code.

That's terrible in terms of performance though - there's really no need
to use a regex here, IMO. Here's code which I believe would be
significantly faster:

if (s.Length != 12)
{
// Whatever your error handling is
}
foreach (char c in s)
{
if (c < '0' || c > '9')
{
// Whatever your error handling is
}
}

return String.Concat(s.Substring(0, 2), ":",
s.Substring(2, 2), ":",
s.Substring(4, 2), ":",
s.Substring(6, 2), ":",
s.Substring(8, 2), ":",
s.Substring(10, 2));

Alternatively, for the last bit:

char[] result = new char[17];
int resultIndex=0;
int origIndex=0;
for (int i=0; i < 6; i++)
{
result[resultIndex++]=s[origIndex++];
result[resultIndex++]=s[origIndex++];
if (i != 5)
{
result[resultIndex++]=':';
}
}
return new string(result);

(That avoids creating too many extra strings.)

I don't know which would be faster - or using a StringBuilder would be
better - but I don't think using a Regex here is a good idea.
 
For asserting that the string is valid you can put this at the top of the method:

Regex ex = new Regex(@"^\d{12}$");
if (!re.IsMatch(s))
throw new ApplicationException("Not a valid string");
 
Jon you are very correct in your assertions. I threw all three solutions
out there in a loop of 30,000 iterations just for fun. The regular
expression code came in about 1.5 seconds for 30,000 iterations. Your first
solution came in at about 0.1 seconds for 30,000 iterations but your second
solution blew them all away coming in at 0.02 seconds for the 30,000
iterations.

Like you am sure the slow down is in the Regular Expressions.
_________________________
C Addison Ritchie, MCSD.NET
Ritch Consulting, Inc.

Jon Skeet said:
C Addison Ritchie said:
This seems to work well.

using System.Text;
using System.Text.RegularExpressions;

// your string "112233445566";
string s = "112233445566";

// create the regular expression
Regex re = new Regex("(\\d\\d)");

// find the matches
MatchCollection matches = re.Matches();

// build the string
string result = String.Format("{0}:{1}:{2}:{3}:{4}:{5}",
matches[0].Value,
matches[1].Value,
matches[2].Value,
matches[3].Value,
matches[4].Value,
matches[5].Value);

return result;

The input string must be 12 characters long and all numbers. I would
assert that this is true before executing the above code.

That's terrible in terms of performance though - there's really no need
to use a regex here, IMO. Here's code which I believe would be
significantly faster:

if (s.Length != 12)
{
// Whatever your error handling is
}
foreach (char c in s)
{
if (c < '0' || c > '9')
{
// Whatever your error handling is
}
}

return String.Concat(s.Substring(0, 2), ":",
s.Substring(2, 2), ":",
s.Substring(4, 2), ":",
s.Substring(6, 2), ":",
s.Substring(8, 2), ":",
s.Substring(10, 2));

Alternatively, for the last bit:

char[] result = new char[17];
int resultIndex=0;
int origIndex=0;
for (int i=0; i < 6; i++)
{
result[resultIndex++]=s[origIndex++];
result[resultIndex++]=s[origIndex++];
if (i != 5)
{
result[resultIndex++]=':';
}
}
return new string(result);

(That avoids creating too many extra strings.)

I don't know which would be faster - or using a StringBuilder would be
better - but I don't think using a Regex here is a good idea.
 
hi

what about this one?

s = "112233445566";
for (int i = 2; i < 15; i += 3)
s = s.Insert(i, ":");

regards
rb
 
Hi,

You are creating lots of several strings, it;s much better to use a
StringBuilder, see my other post for a possible solution.

Cheers,
 
hi

i am creating 5 substrings..

your solution works but has a lot of code..

substring() produces temp strings, too. Also, I suppose StringBuilder
internally works with temporary strings as well.

regards
rb
 
Ralf B. said:
i am creating 5 substrings..

your solution works but has a lot of code..

substring() produces temp strings, too. Also, I suppose StringBuilder
internally works with temporary strings as well.

StringBuilder uses a temporary string if it needs to be expanded, but
if you give it the right size to start with, it shouldn't need any
temporary measures.
 
ok point taken... in this case

StringBuilder sb = new StringBuilder("112233445566", 20);
for (int i = 2; i < 15; i += 3)
sb.Insert(i, ":");
 
Ralf B. said:
ok point taken... in this case

StringBuilder sb = new StringBuilder("112233445566", 20);
for (int i = 2; i < 15; i += 3)
sb.Insert(i, ":");

That would certainly be significantly better, yes. Quite possibly
better than all the other suggestions, although it does involve copying
the data around a bit. (Every time you insert something, you need to
copy the rest of the string.)
 
Hi,

What about:

StringBuilder sb = new StringBuilder( 20)
int start = 0;
string str = "112233445566";
while ( str.Length - start > 2 )
{
if ( start != 0 )
sb.Append( ':' ); // Adding a CHAR
sb.Append( str[ start++] );
sb.Append( str[ start++] );
}

No temp string created :D

Cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation
 
<"Ignacio Machin \( .NET/ C# MVP \)" <ignacio.machin AT
dot.state.fl.us> said:
What about:

StringBuilder sb = new StringBuilder( 20)
int start = 0;
string str = "112233445566";
while ( str.Length - start > 2 )
{
if ( start != 0 )
sb.Append( ':' ); // Adding a CHAR
sb.Append( str[ start++] );
sb.Append( str[ start++] );
}

No temp string created :D

Indeed. I don't know whether the double append is faster than

sb.Append(str, start, 2);

or not.
 
Hi,

:)

Cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation

Jon Skeet said:
<"Ignacio Machin \( .NET/ C# MVP \)" <ignacio.machin AT
dot.state.fl.us> said:
What about:

StringBuilder sb = new StringBuilder( 20)
int start = 0;
string str = "112233445566";
while ( str.Length - start > 2 )
{
if ( start != 0 )
sb.Append( ':' ); // Adding a CHAR
sb.Append( str[ start++] );
sb.Append( str[ start++] );
}

No temp string created :D

Indeed. I don't know whether the double append is faster than

sb.Append(str, start, 2);

or not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top