Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

linq.js to group by array of objects in javascript

I want to use linq.js to group the following data by date.

data2 = [{
    "date": 1399298400.0,
    "adId": 1057946139383,
    "impressions": 1000000
  }, {
    "date": 1399298400.0,
    "adId": 3301784671323,
    "impressions": 535714
  }...... etc.
]; 

Here's my attempt:

var linq = Enumerable.From(data2);
data2 = linq.GroupBy(function (x) {
  return x.date;
}).Select(function (x) {
  return {
    date: x.Key(),
    impressions: x.Sum(function (y) {
      return y.impressions | 0;
    })
  };
}).ToArray();

However, It's not working correctly because the sum of all the impressions before and after the GroupBy are close but not identical.

What is the correct way to use group by in linq.js in this case?

Here's an example in fiddle with full dataset here which alerts the total impressions before and after using the GroupBy.

like image 536
user40721 Avatar asked May 16 '14 21:05

user40721


2 Answers

Solution

You can do this by passing a callback as the third parameter like this:

var grouped = Enumerable.from(dataArray).groupBy("$.person", null, (key, g) => {
  return { 
      person: key, 
      likes: g.sum("$.likes | 0")
 }
}).toArray()

Explanation

In groupBy, the third parameter allows you to modify the results before emitting:

GroupBy > ResultSelector

In JS, the bitwise or operator (a single pipe |) returns the first value if it exists, otherwise it returns the second one. Without it, trying to sum an undefined value with a real one, will return NaN

undefined + 1 // NaN

Without | 0, the result would look like this:

NaN

This example uses shorthand syntax, but if you prefer anytime you see a string with a dollar sign, you can replace it with the lambda syntax like this (they both do the same exact thing):

// Shorthand
.Select("$.impressions")
// Lambda
.Select(function (x) { return x.impressions })

Working demo with Stack Snippets:

var dataArray = [
  {
    person: "james",
    likes: 100
  }, 
  {
    person: "james",
    likes: 250
  }, 
  {
    person: "kyle",
    likes: 300
  }, 
  {
    person: "kyle"
    //,likes: 450
  }
];

var grouped = Enumerable.from(dataArray).groupBy("$.person", null, (key, g) => {
  return { person: key, likes: g.sum("$.likes | 0") }
}).toArray()

console.log(grouped);
<script src="https://unpkg.com/[email protected]/linq.js"></script>

Further Reading:

  • SO - linqjs group by with a sum
like image 80
KyleMit Avatar answered Sep 29 '22 01:09

KyleMit


I am the author of the open source project http://www.jinqJs.com. You can easily do that in jinqJs like this:

jinqJs().from(data2).groupBy('date').sum('impressions').select();

Let me know if I can be of anymore help.

like image 26
NYTom Avatar answered Sep 29 '22 02:09

NYTom