JSON数据的JavaScript SUM和GROUP BY

Lor*_*iot 23 javascript json group-by sum

这是我第一次尝试使用一些JSON数据对象进行JavaScript,并且需要一些关于实现目标的正确方法的建议.

一些服务器端代码实际上生成了一个JSON格式的字符串,我必须使用它并将其分配给字符串:

var dataString='$DATASTRING$';
Run Code Online (Sandbox Code Playgroud)

但是在服务器替换其数据之后我必须使用最终结果(当然没有\ r \n):

var dataString='[ 
 { "category" : "Search Engines", "hits" : 5, "bytes" : 50189 },
 { "category" : "Content Server", "hits" : 1, "bytes" : 17308 },
 { "category" : "Content Server", "hits" : 1, "bytes" : 47412 },
 { "category" : "Search Engines", "hits" : 1, "bytes" : 7601 },
 { "category" : "Business", "hits" : 1, "bytes" : 2847 },
 { "category" : "Content Server", "hits" : 1, "bytes" : 24210 },
 { "category" : "Internet Services", "hits" : 1, "bytes" : 3690 },
 { "category" : "Search Engines", "hits" : 6, "bytes" : 613036 },
 { "category" : "Search Engines", "hits" : 1, "bytes" : 2858 } 
]';
Run Code Online (Sandbox Code Playgroud)

然后我可以将其更改为要使用的对象.

var dataObject=eval("("+dataString+")");
Run Code Online (Sandbox Code Playgroud)

这允许我访问数据的各个数据行,但我需要对值进行求和,分组和排序.

我需要相当于这样的SQL语句:

SELECT category, sum(hits), sum(bytes) 
FROM dataObject
GROUP BY category
ORDER BY sum(bytes) DESC
Run Code Online (Sandbox Code Playgroud)

我想要的输出将是这样的对象,我可以进一步处理:

var aggregatedObject='[ 
 { "category" : "Search Engines", "hits" : 13, "bytes" : 673684 },
 { "category" : "Content Server", "hits" : 3, "bytes" : 88930 },
 { "category" : "Internet Services", "hits" : 1, "bytes" : 3690 },
 { "category" : "Business", "hits" : 1, "bytes" : 2847 } 
]';
Run Code Online (Sandbox Code Playgroud)

......但我不知道从哪里开始.

我可以循环遍历所有类别值并首先找到唯一的类别,然后再次循环并对命中和字节求和,然后再次进行排序,但似乎必须有一种更简单的方法.

prototype.js(1.7)已经包含在客户端页面上,但是如果必须的话,我可以添加Underscore,jQuery或其他一些小型库.

我只是不知道什么是最好的,最简单的,最小的,用最少量的代码来处理查询.

有什么建议?

小智 28

您可以使用本机函数.reduce()来聚合数据,然后.sort()进行排序bytes.

var result = dataObject.reduce(function(res, obj) {
    if (!(obj.category in res))
        res.__array.push(res[obj.category] = obj);
    else {
        res[obj.category].hits += obj.hits;
        res[obj.category].bytes += obj.bytes;
    }
    return res;
}, {__array:[]}).__array
                .sort(function(a,b) { return b.bytes - a.bytes; });
Run Code Online (Sandbox Code Playgroud)

如果您支持较旧的实现,则需要使用垫片.reduce().


Kyl*_*Mit 8

如果你去LINQ.js路线,你可以这样做:

var aggregatedObject = Enumerable.From(dataArray)
        .GroupBy("$.category", null,
                 function (key, g) {
                     return {
                       category: key,
                       hits: g.Sum("$.hits"),
                       bytes: g.Sum("$.bytes")
                     }
        })
        .ToArray();
Run Code Online (Sandbox Code Playgroud)

Stack Snippets的工作演示:

var dataArray = [ 
  { category: "Search Engines", hits: 5, bytes: 50189 },
  { category: "Content Server", hits: 1, bytes: 17308 },
  { category: "Content Server", hits: 1, bytes: 47412 },
  { category: "Search Engines", hits: 1, bytes: 7601  },
  { category: "Business",       hits: 1, bytes: 2847  },
  { category: "Content Server", hits: 1, bytes: 24210 },
  { category: "Internet ",      hits: 1, bytes: 3690  },
  { category: "Search Engines", hits: 6, bytes: 613036 },
  { category: "Search Engines", hits: 1, bytes: 2858  } 
];

var aggregatedObject = Enumerable.From(dataArray)
        .GroupBy("$.category", null,
                 function (key, g) {
                     return {
                       category: key,
                       hits: g.Sum("$.hits"),
                       bytes: g.Sum("$.bytes")
                     }
        })
        .ToArray();

console.log(aggregatedObject);
Run Code Online (Sandbox Code Playgroud)
<script src="//cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

此外,您可以通过总和找到有关linqjs组的更多信息