1

I have string pattern like this:

#c1 12,34,222x8. 45,989,100x10. 767x55. #c1

I want to change these patterns into this:

c1,12,8
c1,34,8
c1,222,8
c1,45,10
c1,989,10
c1,100,10
c1,767,55

My code in C#:

private void btnProses_Click(object sender, EventArgs e)
{
    String ps = txtpesan.Text;
    Regex rx = new Regex("((?:\d+,)*(?:\d+))x(\d+)");
    Match mc = rx.Match(ps);
    while (mc.Success)
    {
        txtpesan.Text = rx.ToString();
    }
}

I've been using split and replace but to no avail. After I tried to solve this problem, I see many people using regex, I tried to use regex but I do not get the logic of making a pattern regex.

What should I use to solve this problem?

2
  • Regular expressions doesn't work well for some type of tasks, like data with unknown number of repetitions in advance. If all your input data will always have 3 groups of values, delimited by . character and you know number of items, separated by comma character is fixed, you can use it. Otherwise it is better to use String.Split(). Is your input data always fixed? Commented Aug 18, 2016 at 8:41
  • Input data is not always have 3 groups could be even less than that Commented Aug 18, 2016 at 8:53

2 Answers 2

2

sometimes regex is not good approach - old school way wins. Assuming valid input:

var tokens = txtpesan.Text.Split(' '); //or use split by regex's whitechar
var prefix = tokens[0].Trim('#');

var result = new StringBuilder();

//skip first and last token
foreach (var token in tokens.Skip(1).Reverse().Skip(1).Reverse())
{
    var xIndex = token.IndexOf("x");
    var numbers = token.Substring(0, xIndex).Split(',');
    var lastNumber = token.Substring(xIndex + 1).Trim('.');

    foreach (var num in numbers)
    {
        result.AppendLine(string.Format("{0},{1},{2}", prefix, num, lastNumber));
    }
}

var viola = result.ToString();
Console.WriteLine(viola);
Sign up to request clarification or add additional context in comments.

3 Comments

thanks for your response sir, I 've tried there is an error in the "appendLine" and I was dangling with "appendFormat" but the result is c1,c1,c1c1,c1,c1c1,c1,c1c1,c1,c1c1,c1,c1c1,c1,c1c1,c1,c1
replace ` result.AppendLine("{0},{0},{0}", prefix, num, lastNumber);` with ` result.AppendLine("{0},{1},{2}", prefix, num, lastNumber);`, @TomiTeruz
I got it , I change it to result.AppendLine(prefix+","+ num + ","+ lastNumber); thank you :)
0

And here comes a somewhat ugly regex based solution:

var q = "#c1 12,34,222x8. 45,989,100x10. 767x55. #c1";
var results = Regex.Matches(q, @"(?:(?:,?\b(\d+))(?:x(\d+))?)+");
var caps = results.Cast<Match>()
     .Select(m => m.Groups[1].Captures.Cast<Capture>().Select(cap => cap.Value));
var trailings = results.Cast<Match>().Select(m => m.Groups[2].Value).ToList();
var c1 = q.Split(' ')[0].Substring(1);
var cnt = 0;
foreach (var grp in caps)
{
     foreach (var item in grp)
     {
         Console.WriteLine("{0},{1},{2}", c1, item, trailings[cnt]);
     }
     cnt++;
}

The regex demo can be seen here. The pattern matches blocks of comma-separated digits while capturing the digits into Group 1, and captures the digits after x into Group 2. Could not get rid of the cnt counter, sorry.

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.