Генерация и объединение функций из коллекций
Я хочу составить последовательность функций, которая при наличии строки пропускает ее через все созданные функции и создает измененную строку. например
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, ""))