1
votes

I want to compose a sequence of functions that when given a string passes it through all the created functions and produces a modified string. e.g.

string[] arr = {"po", "ro", "mo", "do"};

var modify = "pomodoroX";
foreach (var token in arr)
{
    modify = modify.Replace(token, "");
}
Console.WriteLine(modify); // Output: X

This solves the problem, but I am interested in the Functional solution:

Console.WriteLine(
    arr.Select<string, Func<string, string>>(val => (s1 => s1.Replace(val, string.Empty)))
       .Aggregate((fn1, fn2) => fn1 += fn2)
       .Invoke("pomodoroX")
); 
   // Output: pomoroX -> Only last element applied because: 
   // the functions are not getting combined.

So basically, take the array "arr" and for each string create a function that removes that string. The current solution is flawed and applies only the last function and I can't seem to convert this to delegates so as to combine them with += operator.

Or are there better functional solutions?

2

2 Answers

3
votes

Well, your Select gives you the collection of delegates which take in a string, and produce the modified string, so you're halfway there. All you need is to chain these together via Aggregate - and the way you do it is as follows:

string[] arr = { "po", "ro", "mo", "do" };

string result = arr
    // Produce our collection of delegates which take in the string,
    // apply the appropriate modification and return the result.
    .Select<string, Func<string, string>>(val => s1 => s1.Replace(val, string.Empty))
    // Chain the delegates together so that the first one is invoked
    // on the input, and each subsequent one - on the result of
    // the invocation of the previous delegate in the chain.
    // fn1 and fn2 are both Func<string, string>.
    .Aggregate((fn1, fn2) => s => fn2(fn1(s)))
    .Invoke("pomodoroX");

Console.WriteLine(result); // Prints "X".
1
votes

I don't really know what counts as "functional". I assume you don't want to use any flow control structures.

This is simpler, don't you think?

string[] arr = {"po", "ro", "mo", "do"};
arr.Aggregate("pomodoroX", (x, y) => x.Replace(y, ""))