हालांकि linq का जवाब दिलचस्प है, लेकिन यह काफी भारी है। मेरा दृष्टिकोण कुछ अलग है:
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 पर कार्रवाई में देख सकते हैं ।
मैंने अंडरस्कोर में ऐसा कुछ नहीं देखा जो has
करता है, हालांकि मैं इसे याद कर रहा हूं। यह बहुत समान है _.contains
, लेकिन तुलना के _.isEqual
बजाय उपयोग करता है ===
। इसके अलावा, इस के बाकी समस्या-विशिष्ट है, हालांकि सामान्य होने के प्रयास के साथ।
अब DataGrouper.sum(data, ["Phase"])
लौटता है
[
{Phase: "Phase 1", Value: 50},
{Phase: "Phase 2", Value: 130}
]
और DataGrouper.sum(data, ["Phase", "Step"])
लौटता है
[
{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}
]
लेकिन sum
यहां केवल एक संभावित कार्य है। आप जैसे चाहें दूसरों को पंजीकृत कर सकते हैं:
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(data, ["Phase", "Step"])
लौट आएगा
[
{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}
]
या यदि आपने इसे पंजीकृत किया है:
DataGrouper.register("tasks", function(item) {
return _.extend({}, item.key, {Tasks: _.map(item.vals, function(item) {
return item.Task + " (" + item.Value + ")";
}).join(", ")});
});
फिर कॉलिंग DataGrouper.tasks(data, ["Phase", "Step"])
आपको मिल जाएगी
[
{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
अपने आप में एक फ़ंक्शन है। आप इसे अपने डेटा और उन गुणों की एक सूची के साथ कॉल कर सकते हैं जिन्हें आप समूह बनाना चाहते हैं। यह एक सरणी देता है जिसके तत्व दो गुणों के साथ ऑब्जेक्ट हैं: key
समूहित गुणों का संग्रह है, vals
वस्तुओं का एक सरणी है जिसमें शेष गुण हैं जो कुंजी में नहीं हैं। उदाहरण के लिए, DataGrouper(data, ["Phase", "Step"])
उपज होगी:
[
{
"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
आपके द्वारा आपूर्ति किए गए नाम के अनुसार एक संपत्ति के रूप में संग्रहीत किया जाता है और यदि आप केवल एक स्थानीय संदर्भ चाहते हैं तो भी लौटा दिया जाता है।
वैसे यह बहुत स्पष्टीकरण है। कोड यथोचित सीधा है, मुझे उम्मीद है!