Running sum using the Dynamic Linq library

c# dynamic-linq linq

Question

Given the list below:

var items = new List<int> { 1, 2, 3, 5 };

I'm attempting to use the Linq dynamic library to get the total number of prior records for every given record. I could accomplish the following with regular LINQ (LINQ to Objects):

var runningTotal = 0;
var qry1 = items.Select(x => {
    var ret = new { x, runningTotal };
    runningTotal += x;
    return ret;
});

or this (less effective, since it repeatedly iterates through the list's earlier elements). This is clearly not a problem for such a short list, but for longer ones, it will be):

var qry1 = items.Select((x, idx) => new { 
    x, 
    runningTotal = items.Take(idx).Sum()
});

The library does not useTake an overload of a string expressionSelect that takes the element's index. The following, however, comes close:

var qry2 = items.AsQueryable().Select(
    "new(it as x, @0.Where(it < parent).Sum(it) as runningTotal)",
    items
);

However, there are a couple drawbacks to this:

  • The list must be organized; else, the innerWhere will produce random records
  • Similarly, each thing has to be distinct.
  • The second C# example also exhibits the same inefficiency as this.

Is there a method to do this using Dynamic Linq that avoids these issues, and if so, how?


Update

Attempting to write for the following class:

[DynamicLinqType]
public class Aggregator<T> {
    private T state;
    private Func<T, T, T> fn;
    public Aggregator(Func<T, T, T> fn) {
        this.fn = fn;
    }
    public T GetState(T value) {
        state = fn(state, value);
        return state;
    }
}

followed by a question like this:

var aggregator = new Aggregator<int>((runningTotal1, x) => runningTotal1 + x);
var qry4 = items.AsQueryable().Select(
    "new(it as x, @0.GetState(it) - it as runningTotal)", 
    aggregator
);

but I receive aParseException: Methods on type 'Aggregator1' are not accessible in spite of theGetState public method This is because the library confines itself to only utilizing types tagged with and members of certain specified types.DynamicLinqTypeAttribute (by convention). However, the designated typeAggregator<T> is distinct from the created kind.Aggregator<int> ).


2. Update

I've submitted a problem with doing computations and a generic mixtures of known varieties problem.

1
3
11/7/2015 9:57:27 PM

Popular Answer

I did some study and discovered the error:

DynamicLinqType kind of register - in your situationAggregator<T>

the moment you specifyT int, this is already a different variety.Aggregator<int> , andDynamicLinq I believe it is not a predetermined kind.

So as a workaround, just delete the generic part:

[DynamicLinqType]
public class Aggregator
{
    private int state;
    private Func<int, int, int> fn;
    public Aggregator(Func<int, int, int> fn)
    {
        this.fn = fn;
    }
    public int GetState(int value)
    {
        state = fn(state, value);
        return state;
    }
}

UPDATE:
alternative approach - correct this in src

static bool IsPredefinedType(Type type)
{
    if (_predefinedTypes.Contains(type)) return true;

    if (GlobalConfig.CustomTypeProvider.GetCustomTypes().Contains(type)) return true;

    // for generic type check GenericTypeDefinition
    if (type.IsGenericType && GlobalConfig.CustomTypeProvider.GetCustomTypes().Contains(type.GetGenericTypeDefinition())) return true;

    return false;
}
3
11/6/2015 8:51:24 AM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow