Meskipun jawaban LINQ menarik, itu juga cukup berat. Pendekatan saya agak berbeda:
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)});
});
Anda dapat melihatnya beraksi di JSBin .
Saya tidak melihat apa pun di Underscore yang melakukan apa has
, meskipun saya mungkin melewatkannya. Ini hampir sama dengan _.contains
, tetapi menggunakan _.isEqual
daripada ===
untuk perbandingan. Selain itu, sisanya adalah masalah khusus, meskipun dengan upaya untuk menjadi generik.
Sekarang DataGrouper.sum(data, ["Phase"])
kembali
[
{Phase: "Phase 1", Value: 50},
{Phase: "Phase 2", Value: 130}
]
Dan DataGrouper.sum(data, ["Phase", "Step"])
kembali
[
{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}
]
Tetapi sum
hanya satu fungsi potensial di sini. Anda dapat mendaftarkan orang lain sesuka Anda:
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)});
});
dan sekarang DataGrouper.max(data, ["Phase", "Step"])
akan kembali
[
{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}
]
atau jika Anda mendaftarkan ini:
DataGrouper.register("tasks", function(item) {
return _.extend({}, item.key, {Tasks: _.map(item.vals, function(item) {
return item.Task + " (" + item.Value + ")";
}).join(", ")});
});
maka menelepon DataGrouper.tasks(data, ["Phase", "Step"])
akan membuat Anda
[
{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
itu sendiri adalah suatu fungsi. Anda dapat menyebutnya dengan data Anda dan daftar properti yang ingin Anda kelompokkan. Ini mengembalikan array yang elemennya adalah objek dengan dua properti: key
adalah kumpulan properti yang dikelompokkan, vals
adalah array objek yang berisi properti yang tersisa yang tidak ada dalam kunci. Sebagai contoh, DataGrouper(data, ["Phase", "Step"])
akan menghasilkan:
[
{
"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
menerima fungsi dan membuat fungsi baru yang menerima data awal dan properti untuk dikelompokkan berdasarkan. Fungsi baru ini kemudian mengambil format output seperti di atas dan menjalankan fungsi Anda terhadap masing-masing, mengembalikan array baru. Fungsi yang dihasilkan disimpan sebagai properti DataGrouper
sesuai dengan nama yang Anda berikan dan juga dikembalikan jika Anda hanya ingin referensi lokal.
Nah itu banyak penjelasan. Kode ini cukup mudah, saya harap!