Генерация и объединение функций из коллекций

Я хочу составить последовательность функций, которая при наличии строки пропускает ее через все созданные функции и создает измененную строку. например

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

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

Это решает проблему, но меня интересует функциональное решение:

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.

Итак, в основном, возьмите массив "arr" и для каждой строки создайте функцию, которая удаляет эту строку. Текущее решение имеет недостатки и применяет только последнюю функцию, и я не могу преобразовать это в делегаты, чтобы объединить их с += оператор.

Или есть лучшие функциональные решения?

2 ответа

Решение

Ну твой Select дает вам набор делегатов, которые принимают строку и создают измененную строку, так что вы на полпути. Все, что вам нужно, это связать их вместе через Aggregate - и как ты это делаешь так:

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".

Я действительно не знаю, что считается "функциональным". Я предполагаю, что вы не хотите использовать какие-либо структуры управления потоком.

Это проще, тебе не кажется?

string[] arr = {"po", "ro", "mo", "do"};
arr.Aggregate("pomodoroX", (x, y) => x.Replace(y, ""))
Другие вопросы по тегам