son - Extensiones genéricas de listas en C#
comparar elementos de una lista c# (4)
Estoy escribiendo algunas extensiones para imitar el mapa y reducir funciones en Lisp.
public delegate R ReduceFunction<T,R>(T t, R previous);
public delegate void TransformFunction<T>(T t, params object[] args);
public static R Reduce<T,R>(this List<T> list, ReduceFunction<T,R> r, R initial)
{
var aggregate = initial;
foreach(var t in list)
aggregate = r(t,aggregate);
return aggregate;
}
public static void Transform<T>(this List<T> list, TransformFunction<T> f, params object [] args)
{
foreach(var t in list)
f(t,args);
}
La función de transformación reducirá a cruft como:
foreach(var t in list)
if(conditions && moreconditions)
//do work etc
¿Esto tiene sentido? ¿Podría ser mejor?
Es posible que desee agregar una forma de hacer un mapa pero devolver una nueva lista, en lugar de trabajar en la lista pasada (y devolver la lista puede ser útil para encadenar otras operaciones) ... quizás una versión sobrecargada con un booleano que indique si desea devolver una nueva lista o no, como tal:
public static List<T> Transform<T>(this List<T> list, TransformFunction<T> f,
params object [] args)
{
return Transform(list, f, false, args);
}
public static List<T> Transform<T>(this List<T> list, TransformFunction<T> f,
bool create, params object [] args)
{
// Add code to create if create is true (sorry,
// too lazy to actually code this up)
foreach(var t in list)
f(t,args);
return list;
}
Estos parecen muy similares a las extensiones en Linq ya:
//takes a function that matches the Func<T,R> delegate
listInstance.Aggregate(
startingValue,
(x, y) => /* aggregate two subsequent values */ );
//takes a function that matches the Action<T> delegate
listInstance.ForEach(
x => /* do something with x */);
¿Por qué el segundo ejemplo se llama Transformar? ¿Tiene la intención de cambiar los valores en la lista de alguna manera? Si ese es el caso, es mejor que ConvertAll<T>
o Select<T>
.
Yo usaría los delegados integrados de Func en su lugar. Este mismo código funcionaría en cualquier IEnumerable. Tu código se convertiría en:
public static R Reduce<T,R>(this IEnumerable<T> list, Func<T,R> r, R initial)
{
var aggregate = initial;
foreach(var t in list)
aggregate = r(t,aggregate);
return aggregate;
}
public static void Transform<T>(this IEnumerable<T> list, Func<T> f)
{
foreach(var t in list)
f(t);
}
De acuerdo con este enlace Programación Funcional en C # 3.0: Cómo Mapa / Reducir / Filtrar puede Oscilar el Mundo, los siguientes son equivalentes en C # bajo el espacio de nombres System.Linq:
- mapa -> Enumerable.Select
- reducir -> Enumerable.Aggregate
- filter -> Enumerable.Where