C#中的通用Map / Reduce列表扩展

时间:2020-03-05 18:46:36  来源:igfitidea点击:

我正在编写一些扩展程序来模拟地图并简化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);
}

转换功能将减少残骸,例如:

foreach(var t in list)
    if(conditions && moreconditions)
        //do work etc

这有意义吗?会更好吗?

解决方案

回答

我会改用内置的Func委托。相同的代码可在任何IEnumerable上使用。代码将变成:

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);
}

回答

我们可能想添加一种做映射的方法,但是返回一个新列表,而不是处理传入的列表(返回列表可以证明对链接其他操作很有用)...也许是带有布尔值的重载版本,它指示如果我们想返回一个新列表,例如:

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;
}

回答

这些看起来已经与Linq中的扩展非常相似:

//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 */);

为什么第二个示例称为"变换"?我们打算以某种方式更改列表中的值吗?如果是这种情况,最好使用ConvertAll &lt;T>或者Select &lt;T>

回答

根据此链接,其中包含C3.0中的"函数编程":Map / Reduce / Filter如何影响世界,以下是System.Linq命名空间下的等效项:

  • 贴图-> Enumerable.Select
  • 减少-> Enumerable.Aggregate
  • 过滤器->可枚举。