TResult to Function Signature? I am very c...">

In LINQ, how do I modify an existing LINQ extension method to add a "By" selector, i.e. Add Func <T> TResult to Function Signature?

I am very curious to learn how to modify an existing LINQ function to add Func<T> TResultfunctions to the signature, i.e. allow her to use the selector as in (o => o.CustomField).

For example, in C # I can use .IsDistinct()to check if a list of integers is great. I can also use .IsDistinctBy(o => o.SomeField)to check if the integers in the field are o.SomeFielddifferent. I find that backstage .IsDistinctBy(...)has something like a function attached to itFunc<T> TResult

My question is this: what is the technique for taking the existing LINQ extension function and transforming it so that it can have a parameter (o => o.SomeField)?

Here is an example.

This extension function checks if the list grows monotonously (i.e. the values ​​never decrease, as in 1,1,2,3,4,5,5):

main()
{
   var MyList = new List<int>() {1,1,2,3,4,5,5};
   DebugAssert(MyList.MyIsIncreasingMonotonically() == true);
}

public static bool MyIsIncreasingMonotonically<T>(this List<T> list) where T : IComparable
{
    return list.Zip(list.Skip(1), (a, b) => a.CompareTo(b) <= 0).All(b => b);
}

If I want to add "By", I add a parameter Func<T> TResult. But how do I change the function body to make it a choice (o => o.SomeField)?

main()
{
   DebugAssert(MyList.MyIsIncreasingMonotonicallyBy(o => o.CustomField) == true);
}

public static bool MyIsIncreasingMonotonicallyBy<T>(this List<T> list, Func<T> TResult) where T : IComparable
{
    // Question: How do I modify this function to make it  
    // select by o => o.CustomField?
    return list.Zip(list.Skip(1), (a, b) => a.CompareTo(b) <= 0).All(b => b);
}
+5
source share
4 answers

Consider an implementation similar to the following, which lists a given IEnumerable<T>one only once. Listing can have side effects, and callers usually expect a single pass, if possible.

public static bool IsIncreasingMonotonically<T>(
    this IEnumerable<T> _this)
    where T : IComparable<T>
{
    using (var e = _this.GetEnumerator())
    {
        if (!e.MoveNext())
            return true;
        T prev = e.Current;
        while (e.MoveNext())
        {
            if (prev.CompareTo(e.Current) > 0)
                return false;
            prev = e.Current;
        }
        return true;
    }
}

enumerable.IsIncreasingMonotonicallyBy(x => x.MyProperty) .

public static bool IsIncreasingMonotonicallyBy<T, TKey>(
    this IEnumerable<T> _this,
    Func<T, TKey> keySelector)
    where TKey : IComparable<TKey>
{
    return _this.Select(keySelector).IsIncreasingMonotonically();
}
+4

Func a b:

public static bool MyIsIncreasingMonotonicallyBy<T, TResult>(this IEnumerable<T> list, Func<T, TResult> selector)
    where TResult : IComparable<TResult>
{
    return list.Zip(list.Skip(1), (a, b) => selector(a).CompareTo(selector(b)) <= 0).All(b => b);
}
+3

, :

  • IEnumeration

    public static bool MyIsIncreasingMonotonicallyBy<T, TResult>(
            this IEnumerable<T> list, Func<T, TResult> selector)
        where TResult : IComparable<TResult>
    {
        var enumerable = list as IList<T> ?? list.ToList();
        return enumerable.Zip(
                   enumerable.Skip(1),
                   (a, b) => selector(a).CompareTo(selector(b)) <= 0
               ).All(b => b);
    }
    

P.S. , "this", , .


:

:

IEnumerable<string> names = GetNames();
foreach (var name in names)   Console.WriteLine("Found " + name);
var allNames = new StringBuilder();
foreach (var name in names)   allNames.Append(name + " ");

, GetNames() IEnumerable, , foreach. GetNames() , , .

This problem can be easily fixed - just force the enumeration at the initialization point of the variable, converting the sequence to a list (or you can make an array). Both array and list types implement the IEnumerable interface.

0
source
// the existing LINQ operator that you want to modify:
public static … Foo<T>(this IEnumerable<T> xs, …)
{
}

// the extended ("modified") operator:
public static … FooBy<T, U>(this IEnumerable<T> xs, Func<T, U> func)
{
    return xs.Select(func).Foo(…);
}       // --^^^^^^^^^^^^^-------
        //   there you go!
0
source

All Articles