문제

나는 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

이게 말이 돼?더 좋을 수도 있나요?

도움이 되었습니까?

해결책

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

두 번째 예가 Transform이라고 불리는 이유는 무엇입니까?어떻게든 목록의 값을 변경하시겠습니까?그렇다면 다음을 사용하는 것이 더 나을 수도 있습니다. ConvertAll<T> 또는 Select<T>.

다른 팁

이 링크에 따르면 C# 3.0의 함수형 프로그래밍:Map/Reduce/Filter가 세상을 뒤흔드는 방법 다음은 System.Linq 네임스페이스에 있는 C#의 해당 항목입니다.

대신 내장된 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를 사용하는 확장 방법을 만드는 것이 좋습니다 이와 같이:

public static IEnumerable<R> Map<T, R>(this IEnumerable<T> self, Func<T, R> selector) {
    return self.Select(selector);
}

public static T Reduce<T>(this IEnumerable<T> self, Func<T, T, T> func) {
    return self.Aggregate(func);
}

public static IEnumerable<T> Filter<T>(this IEnumerable<T> self, Func<T, bool> predicate) {
    return self.Where(predicate);
}

다음은 몇 가지 사용 예입니다.

IEnumerable<string> myStrings = new List<string>() { "1", "2", "3", "4", "5" };
IEnumerable<int> convertedToInts = myStrings.Map(s => int.Parse(s));
IEnumerable<int> filteredInts = convertedToInts.Filter(i => i <= 3); // Keep 1,2,3
int sumOfAllInts = filteredInts.Reduce((sum, i) => sum + i); // Sum up all ints
Assert.Equal(6, sumOfAllInts); // 1+2+3 is 6

(보다 https://github.com/cs-util-com/cscore#ienumerable-extensions 더 많은 예를 보려면)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top