么是GROUPBY对象的JavaScript阵列上的最有效的方法

么是GROUPBY对象的JavaScript阵列上的最有效的方法

本文介绍了什么是GROUPBY对象的JavaScript阵列上的最有效的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是GROUPBY在数组对象的最有效方法是什么?

What is the most efficient way to groupby objects in an array?

例如,鉴于此数组对象:

For example, given this array of objects:

[
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
]

我在显示表信息。我想GROUPBY不同的方法,但我想总结的值。

I'm displaying this information in a table. I'd like to groupby different methods, but I want to sum the values.

我使用underscore.js其GROUPBY功能,这是有益的,但​​并没有做到全招了,因为我不想让他们分手,但合并,更像是SQL集团 - 用方法。

I'm using underscore.js for its groupby function, which is helpful, but doesn't do the whole trick, because I don't want them "split up" but "merged", more like the SQL group-by method.

我正在寻找将能够以总价特定值(如果需要)。

What I'm looking for would be able to total specific values (if requested).

所以,如果我没有GROUPBY阶段,我想收到:

So if I did groupby Phase, I'd want to receive:

[
    { Phase: "Phase 1", Value: 50 },
    { Phase: "Phase 2", Value: 130 }
]

如果我做了groupy阶段/步骤,我会得到:

And if I did groupy Phase / Step, I'd receive:

[
    { Phase: "Phase 1", Step: "Step 1", Value: 15 },
    { Phase: "Phase 1", Step: "Step 2", Value: 35 },
    { Phase: "Phase 2", Step: "Step 1", Value: 55 },
    { Phase: "Phase 2", Step: "Step 2", Value: 75 }
]

是否有这一个有用的脚本,或者我应该坚持使用underscore.js,然后通过循环生成的对象做总计自己?

Is there a helpful script for this, or should I stick to using underscore.js, and then looping through the resulting object to do the totals myself?

推荐答案

虽然的回答很有趣,这也是颇重​​的重量。我的方法是有所不同的:

Although the linq answer is interesting, it's also quite heavy-weight. My approach is somewhat different:

var DataGrouper = (function() {
    var has = function(obj, target) {
        return _.any(obj, function(value) {
            return _.isEqual(value, target);
        });
    };

    var keys = function(data, names) {
        return _.reduce(data, function(memo, item) {
            var key = _.pick(item, names);
            if (!has(memo, key)) {
                memo.push(key);
            }
            return memo;
        }, []);
    };

    var group = function(data, names) {
        var stems = keys(data, names);
        return _.map(stems, function(stem) {
            return {
                key: stem,
                vals:_.map(_.where(data, stem), function(item) {
                    return _.omit(item, names);
                })
            };
        });
    };

    group.register = function(name, converter) {
        return group[name] = function(data, names) {
            return _.map(group(data, names), converter);
        };
    };

    return group;
}());

DataGrouper.register("sum", function(item) {
    return _.extend({}, item.key, {Value: _.reduce(item.vals, function(memo, node) {
        return memo + Number(node.Value);
    }, 0)});
});

您可以看到JSBin 在用行动表明

You can see it in action on JSBin.

我没有看到下划线什么,做什么呢,虽然我可能会丢失了。这是一样一样的 _。包含,但使用 _。isEqual:方法,而不是 == = 进行比较。除此之外,此剩下的特定问题,虽然企图是通用

I didn't see anything in Underscore that does what has does, although I might be missing it. It's much the same as _.contains, but uses _.isEqual rather than === for comparisons. Other than that, the rest of this is problem-specific, although with an attempt to be generic.

现在 DataGrouper.sum(数据,[相位])返回

[
    {Phase: "Phase 1", Value: 50},
    {Phase: "Phase 2", Value: 130}
]

DataGrouper.sum(数据,[相位,步])返回

[
    {Phase: "Phase 1", Step: "Step 1", Value: 15},
    {Phase: "Phase 1", Step: "Step 2", Value: 35},
    {Phase: "Phase 2", Step: "Step 1", Value: 55},
    {Phase: "Phase 2", Step: "Step 2", Value: 75}
]


是这里只有一个势函数。你可以注册人,只要你喜欢:


But sum is only one potential function here. You can register others as you like:

DataGrouper.register("max", function(item) {
    return _.extend({}, item.key, {Max: _.reduce(item.vals, function(memo, node) {
        return Math.max(memo, Number(node.Value));
    }, Number.NEGATIVE_INFINITY)});
});

现在 DataGrouper.max(数据,[相位,步])将返回

[
    {Phase: "Phase 1", Step: "Step 1", Max: 10},
    {Phase: "Phase 1", Step: "Step 2", Max: 20},
    {Phase: "Phase 2", Step: "Step 1", Max: 30},
    {Phase: "Phase 2", Step: "Step 2", Max: 40}
]

或者如果你注册了这个:

or if you registered this:

DataGrouper.register("tasks", function(item) {
    return _.extend({}, item.key, {Tasks: _.map(item.vals, function(item) {
      return item.Task + " (" + item.Value + ")";
    }).join(", ")});
});

然后调用 DataGrouper.tasks(数据,[相位,步])将让你

[
    {Phase: "Phase 1", Step: "Step 1", Tasks: "Task 1 (5), Task 2 (10)"},
    {Phase: "Phase 1", Step: "Step 2", Tasks: "Task 1 (15), Task 2 (20)"},
    {Phase: "Phase 2", Step: "Step 1", Tasks: "Task 1 (25), Task 2 (30)"},
    {Phase: "Phase 2", Step: "Step 2", Tasks: "Task 1 (35), Task 2 (40)"}
]

DataGrouper 本身就是一个功能。您可以与您的数据和您想要组的属性列表来调用它。它返回一个数组的元素是对象具有两个属性:是分组属性的集合,丘壑是一个数组的含有剩余的属性没有在密钥对象。例如, DataGrouper(数据,[相位,步])将产生:

DataGrouper itself is a function. You can call it with your data and a list of the properties you want to group by. It returns an array whose elements are object with two properties: key is the collection of grouped properties, vals is an array of objects containing the remaining properties not in the key. For example, DataGrouper(data, ["Phase", "Step"]) will yield:

[
    {
        "key": {Phase: "Phase 1", Step: "Step 1"},
        "vals": [
            {Task: "Task 1", Value: "5"},
            {Task: "Task 2", Value": "10"}
        ]
    },
    {
        "key": {Phase: "Phase 1", Step: "Step 2"},
        "vals": [
            {Task: "Task 1", Value: "15"},
            {Task: "Task 2", Value: "20"}
        ]
    },
    {
        "key": {Phase: "Phase 2", Step: "Step 1"},
        "vals": [
            {Task: "Task 1", Value: "25"},
            {Task: "Task 2", Value: "30"}
        ]
    },
    {
        "key": {Phase: "Phase 2", Step: "Step 2"},
        "vals": [
            {Task: "Task 1", Value: "35"},
            {Task: "Task 2", Value: "40"}
        ]
    }
]

DataGrouper.register 接受的函数,并且创建由接收的初始数据和属性,以组的新功能。这个新的功能需要的输出格式如上并运行你的函数对每个人依次返回一个新的数组。这是生成的函数存储为一个属性 DataGrouper 根据您提供的,也退回,如果你只是想要一个局部引用的名称。

DataGrouper.register accepts a function and creates a new function which accepts the initial data and the properties to group by. This new function then takes the output format as above and runs your function against each of them in turn, returning a new array. The function that's generated is stored as a property of DataGrouper according to a name you supply and also returned if you just want a local reference.

嗯,这是一个很大的解释。在code是相当简单,我希望!

Well that's a lot of explanation. The code is reasonably straightforward, I hope!

这篇关于什么是GROUPBY对象的JavaScript阵列上的最有效的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!