2
\$\begingroup\$

I wrote some string-extensions:

public static class RegexStringExtensions
{
    public static string PatternReplace(
        this string seed, string pattern, 
        Func<string, string> outPattern)
    {
        return Regex.Replace(seed, pattern, s => outPattern(s.Groups[1].Value));
    }

    public static string PatternReplace(
        this string seed, string pattern, 
        Func<string, string, string> outPattern)
    {
        return Regex.Replace(seed, pattern, s => outPattern(s.Groups[1].Value, s.Groups[2].Value));
    }
    public static string PatternReplace(
        this string seed, string pattern, 
        Func<string, string, string, string> outPattern)
    {
        return Regex.Replace(seed, pattern, s => outPattern(s.Groups[1].Value, s.Groups[2].Value, s.Groups[3].Value));
    }
    public static string PatternReplace(
        this string seed, string pattern, 
        Func<string, string, string, string, string> outPattern)
    {
        return Regex.Replace(seed, pattern, s => outPattern(s.Groups[1].Value, s.Groups[2].Value, s.Groups[3].Value, s.Groups[4].Value));
    }
}

with those, I could handle a replacement for regex-pattern and work with the groups more in C#-way like (just an easy example):

string val = 
    "abcdef".PatternReplace(@"(ab)(cd)(ef)", (s,t,u) => u + string.Concat(s.Reverse()));
// result is "efba"

I think it's not that nice, to have so many overloads since I could have like 10 groups or something. Any idea how I could make this a bit nicer? For now, it'd work with up to 4 parameters, but with also 4 overloads.

\$\endgroup\$
  • \$\begingroup\$ What's bad with those overloads? If you need an extra parameter you just add it to your lambda, no need to also change method name (PatternReplace1, PatternReplace2, etc? nooo) \$\endgroup\$ – Adriano Repetti Feb 8 '17 at 14:19
  • \$\begingroup\$ @AdrianoRepetti would be nice to have something like params for generics. would save me a lot of code...- so you wouldn't change anything and just go with e.g. 10 overloads? \$\endgroup\$ – Matthias Burger Feb 8 '17 at 14:22
  • \$\begingroup\$ Honestly I'd stop with 2 overloads (3 at maximum). At the calling point a lambda with so many parameters will be (IMO) pretty hard to read and a traditional approach preferable. Well, it's just my POV. Note that nothing stops you to have an extra Func<string[], string> overload (sacrifyng readability) \$\endgroup\$ – Adriano Repetti Feb 8 '17 at 14:35
  • \$\begingroup\$ a lambda with so many parameters will be (IMO) pretty hard to read good point! Mh I think I will go with only 4 parameters. I don't think I will ever use more than 4 groups... otherwise I simply will use the Regex-class if I got more than 4 params \$\endgroup\$ – Matthias Burger Feb 8 '17 at 14:39
1
\$\begingroup\$

I'm not saying I like this but you could reuse the longest overload for the shorter ones. Here I took the one that takes three parameters.

public static string PatternReplace(
    this string seed, 
    string pattern,
    Func<string, string> outPattern
)
{
    return seed.PatternReplace(pattern, (x, y, z) => outPattern(x));
}

public static string PatternReplace(
    this string seed, 
    string pattern,
    Func<string, string, string> outPattern
)
{
    return seed.PatternReplace(pattern, (x, y, z) => outPattern(x, y));
}

Here's another small experiment with C# 7 where you could use anonymous tuples with only one method. But actually you could return a tuple in you current solution too.

public static class RegexStringExtensions
{   
    public static string PatternReplace(
        this string seed, 
        string pattern,
        Func<(string, string, string), string> outPattern
    )
    {
        return Regex.Replace(
            seed, 
            pattern, 
            m => outPattern((
                m.Groups[1].Value, 
                m.Groups[2].Value, 
                m.Groups[3].Value)
            )
        );
    }
}

Usage:

string val = "abcdef".PatternReplace(
    @"(ab)(cd)(ef)", 
    t => t.Item1 + string.Concat(t.Item2.Reverse())
);
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ wow, okay, that's an approach I could experiment with. Didn't know working with s.th. like Func<(string, string, string), string> (but first, need to check for C#7) \$\endgroup\$ – Matthias Burger Feb 8 '17 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.