سؤال

أنا أكتب بضع امتداد لتقليد خريطة والحد من وظائف في اللثغة.

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

لماذا هو 2nd سبيل المثال تسمى تحويل ؟ هل تنوي تغيير القيم في قائمة بطريقة أو بأخرى ؟ إذا كان هذا هو الحال قد يكون أفضل حالا باستخدام ConvertAll<T> أو Select<T>.

نصائح أخرى

وفقا لهذا الرابط البرمجة الوظيفية في C# 3.0:كيف الخريطة/تقليل/تصفية يمكن أن صخرة العالم الذي تعيشون فيه وفيما يلي ما يعادلها في C# بموجب النظام.Linq مساحة:

وأود أن استخدام المدمج في وظائفها المندوبين بدلا من ذلك.نفس هذه المدونة أن تعمل على أي 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