5

This might seems like an easy question but I'm struggling with the linqjs syntax.

Given the following basic JSON:

{
    "DateEvent": "2013-04-23 14:00:00Z",
    "DateRecord": "2013-04-23 14:00:00Z",
    "Amount": -9500,
    "Type": {
        "Description": "Capital"
    },
    "Currency": {
        "ID": "USD"
    }
}

Using linqjs how can I return the total for each currency?

Enumerable.From(data)
    .GroupBy("{ currency: $.Currency.ID }", null, function (key, g) {
        var result = {
            currency: key.currency,
            total: g.Sum($.Amount)
        }
    });

The code above doesn't work.

KyleMit
  • 30,350
  • 66
  • 462
  • 664
paligap
  • 942
  • 1
  • 12
  • 28

5 Answers5

7

You almost had it. Your key selector in your GroupBy and Sum is incorrect. Also the key selector needs to be a string. Try the following:

var result = Enumerable.from(data).groupBy("$.Currency.ID", null,
    function (key, g) {
        var result = {
            currency: key,
            total: g.sum("$.Amount")
        }
        return result;
    }).ToArray();
A Farmanbar
  • 4,381
  • 5
  • 24
  • 42
Rei Mavronicolas
  • 1,387
  • 9
  • 12
3

I am the author of the open-source project http://www.jinqJs.com

You could easily do it by executing:

new jinqJs().from(data).groupBy('Currency').sum('Amount').select();
A Farmanbar
  • 4,381
  • 5
  • 24
  • 42
NYTom
  • 524
  • 2
  • 14
1

Just to expand further on this question.

The following syntax will group the data by an additional field:

var result = Enumerable.from(data)
                       .groupBy("{ currency: $.Currency.ID, type: $.Type.Description }", null,
                            function (key, g) {
                                var result = {
                                     currency: key.currency,
                                     type: key.type,
                                     total: g.Sum("$.Amount")
                                }
                                return result;
                                }, function (x) { return x.currency + ':' + x.type }).ToArray();
A Farmanbar
  • 4,381
  • 5
  • 24
  • 42
paligap
  • 942
  • 1
  • 12
  • 28
1

Assuming you have an array of objects that looks like that, you can write your query like this:

var query = Enumerable.from(data)
    .groupBy(
        "{ Currency: $.Currency.ID, Type: $.Type.Description }",
        "$.Amount",
        "{ Currency: $.Currency, Type: $.Type, Total: $$.Sum() }"
    )
    .ToArray();

Personally I find using the lambda string syntax more succinct and preferable. Mixing lambdas and functions leads to messier code IMHO.

A Farmanbar
  • 4,381
  • 5
  • 24
  • 42
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
1

Update with Native JS

With widespread support for JS operations in nearly any browser and the proliferation of build tools to compile down when necessary, unless you're already importing linqjs, I'd recommend going with a native JS approach.

const grouped = data.reduce((acc, el) => {
  const key = el.Currency.ID
  const prev = acc[key] ?? 0
  acc[key] = prev + el.Amount;
  return acc;
}, {})

Demo in Stack Snippets

const data = [
    {
        "Amount": 5,
        "Currency": { "ID": "USD" }
    },
    {
        "Amount": 10,
        "Currency": { "ID": "USD" }
    },
    {
        "Amount": 20,
        "Currency": { "ID": "CAN" }
    }
]

const grouped = data.reduce((acc, el) => {
  const key = el.Currency.ID
  const prev = acc[key] ?? 0
  acc[key] = prev + el.Amount;
  return acc;
}, {})

console.log(grouped)

// {
//     "USD": 15,
//     "CAN": 20
// }

See Also: How to group by and sum an array of objects?

KyleMit
  • 30,350
  • 66
  • 462
  • 664