Surely someone will come with a Regex solution, which in theory is better than what you are doing (generates several needless memory allocations and presses the GC), but for me to do in hand is unbeatable.
I used the StringBuilder
to avoid multiple allocations. I converted to ToString()
at the end and there WriteLine()
I didn’t need to because he does automatic, but I did because in your code you’ll need to do the conversion.
The basic rule would be to sweep the whole string and go copying each character, could even use LINQ, filtering when it is not digit and exchange for ;
(I understood that anything that is not digit should convert, but the question does not make it so clear). So far it’s easy, the problem is you can’t repeat the ;
if it is already present. Then have to assemble a state machine.
I created a control variable that indicates if the last character analyzed is a digit. I start by considering that it is.
Whenever it is digit and the previous one was not a digit must concatenate the ;
, After all if it was an irregular character before and now I will start putting digit, I need to mark with the special character chosen. And obviously if it’s a digit I have to say that the current one is this, for in the next step the algorithm know what to do.
When it is not a digit it is better to do nothing, after all you have to disappear with this character, it cannot be shown. The only action is to identify that now is not a digit in the control variable.
The secret is to kill every invalid character without exception, and before you start concatenating a sequence of digits (may even be a single in the sequence), put the special separator character chosen, but never once it starts.
To create a state machine you have to think about how one would work. What decision to make with each character being analyzed. It’s how a compiler works.
If I understood the rule correctly the code would be this (can you encapsulate in a generic method:
using static System.Console;
using System.Text;
public class Program {
public static void Main() {
var hs = "/4587 / 5458/";
var texto = new StringBuilder(hs.Length);
var digito = true;
foreach (var chr in hs) {
if (char.IsDigit(chr)) {
if (!digito) texto.Append(';');
texto.Append(chr);
digito = true;
} else digito = false;
}
WriteLine(texto.ToString());
}
}
Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.
Maybe you can optimize even more with the new Span<T>
, but I won’t risk that complication for you.
Put your code and where you’re having trouble, and test data.
– Maniero
Was better explained?
– Renan
Yes, although you could have formatted it right, just see the icons there on the edit screen.
– Maniero