5

我想使用 linq.js 按日期对以下数据进行分组。

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

这是我的尝试:

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();

但是,它无法正常工作,因为所有impressions之前和之后的总和GroupBy都很接近但不相同。

在这种情况下,在 linq.js 中使用 group by 的正确方法是什么?

这是一个使用完整数据集的示例,GroupBy它会在使用.

4

4 回答 4

9

解决方案

您可以通过将回调作为第三个参数传递来做到这一点,如下所示:

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

解释

groupBy中,第三个参数允许您在发出之前修改结果:

分组依据 > 结果选择器

在 JS 中,按位或运算符(单个管道|)如果存在则返回第一个值,否则返回第二个值。没有它,试图将一个未定义的值与一个真实的值相加,将返回NaN

undefined + 1 // NaN

如果没有| 0,结果将如下所示:

钠

此示例使用速记语法,但如果您希望看到带有美元符号的字符串,您可以将其替换为 lambda 语法,如下所示(它们都做同样的事情):

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

使用 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/linq@3.2.0/linq.js"></script>

延伸阅读:

于 2014-12-13T06:13:25.380 回答
4

我是开源项目http://www.jinqJs.com的作者。您可以像这样在 jinqJs 中轻松做到这一点:

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

让我知道我是否可以提供帮助。

于 2015-03-30T18:22:19.423 回答
0

您可以尝试按 date.toString() 分组。由于 JS 如何评估日期相等性,可能更安全

于 2017-09-25T05:01:46.270 回答
0

或者,遇到这个问题的人可能对使用 linq.js 有零到很多的购买。

如果您已经开始使用它,那就去做吧,但如果这是它的前几个真正的用例,那么值得注意的是,您可以在vanilla js中完成同样的事情:

对于此数据:

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

您可以为每个键/人构建一个具有属性的对象,并不断总结这些道具的值

var obj = dataArray.reduce((acc, cur) => {
    acc[cur.person] = (acc[cur.person] || 0) + (cur.likes || 0)
    return acc
}, {})

如果你希望它是一个对象数组,你可以像这样从一个对象转换为数组

var array = Object.entries(obj).map(entry => {
    return { person: entry[0], likes: entry[1] }
})
于 2019-04-25T14:25:37.647 回答