linq.js 按javascript中的对象数组分组

Posted

技术标签:

【中文标题】linq.js 按javascript中的对象数组分组【英文标题】:linq.js to group by array of objects in javascript 【发布时间】:2014-07-05 11:38:21 【问题描述】:

我想使用 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();

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

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

这是an example in fiddle,此处包含完整的数据集,用于提醒使用GroupBy 前后的总展示次数。

【问题讨论】:

在我看来,| 0 是造成问题的原因。我从另一个 *** 帖子中复制了这段代码。 | 0 到底是做什么的? 我应该是||而不是|,这意味着如果表达式左侧的对象是null,则返回右侧的内容,即0 那么出于好奇 - 只是 `` 做什么? 【参考方案1】:

解决方案

你可以通过像这样传递一个回调作为第三个参数来做到这一点:

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

说明

groupBy中,第三个参数允许你在发射前修改结果:

在 JS 中,bitwise or operator(单管道|)如果存在则返回第一个值,否则返回第二个。没有它,尝试将未定义的值与真实值相加,​​将返回 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>

延伸阅读:

SO - linqjs group by with a sum

【讨论】:

【参考方案2】:

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

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

如果我能提供更多帮助,请告诉我。

【讨论】:

【参考方案3】:

您可以尝试按 date.toString() 分组。由于 JS 如何评估 dates equality 可能更安全

【讨论】:

【参考方案4】:

另外,遇到这个问题的人可能对使用 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] 
)

【讨论】:

以上是关于linq.js 按javascript中的对象数组分组的主要内容,如果未能解决你的问题,请参考以下文章

如何在javascript中按属性查找数组中的对象?

按Javascript中的角色数组过滤用户对象的数组

如何使用 JavaScript/jQuery 按数组或对象中的多个项目进行索引?

JavaScript对象数组如何按指定属性和排序方

Javascript => 按日期相互匹配数组元素

将javascript数组中的重复值分组在一起,然后按值名称升序对这些组进行排序