मैं थोड़ा अधिक सामान्य-उद्देश्य दृष्टिकोण लेता हूं, हालांकि विचारों में @Cerbrus और @Kasper Moerch दोनों के समान हैं । मैं एक ऐसा फ़ंक्शन बनाता हूं जो यह निर्धारित करने के लिए एक विधेय को स्वीकार करता है कि क्या दो वस्तुएं समान हैं (यहां हम $$hashKey
संपत्ति की उपेक्षा करते हैं, लेकिन यह कुछ भी हो सकता है) और एक ऐसा फ़ंक्शन लौटाता है जो उस विधेय के आधार पर दो सूचियों के सममित अंतर की गणना करता है:
a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"}, { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]
var makeSymmDiffFunc = (function() {
var contains = function(pred, a, list) {
var idx = -1, len = list.length;
while (++idx < len) {if (pred(a, list[idx])) {return true;}}
return false;
};
var complement = function(pred, a, b) {
return a.filter(function(elem) {return !contains(pred, elem, b);});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
var myDiff = makeSymmDiffFunc(function(x, y) {
return x.value === y.value && x.display === y.display;
});
var result = myDiff(a, b); //=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}
सेरेब्रस के दृष्टिकोण पर इसका एक मामूली फायदा है (जैसा कि कास्पर मॉर्च का दृष्टिकोण है) कि यह जल्दी बच जाता है; यदि यह एक मैच पाता है, तो यह बाकी सूची की जाँच करने में परेशान नहीं करता है। अगर मेरे पास कोई curry
फ़ंक्शन होता, तो मैं इसे थोड़ा अलग तरीके से करता, लेकिन यह ठीक काम करता है।
व्याख्या
एक टिप्पणी ने शुरुआती लोगों के लिए अधिक विस्तृत स्पष्टीकरण के लिए कहा। यहाँ एक प्रयास है।
हम निम्न फ़ंक्शन पास करते हैं makeSymmDiffFunc
:
function(x, y) {
return x.value === y.value && x.display === y.display;
}
यह फ़ंक्शन है कि हम कैसे तय करते हैं कि दो ऑब्जेक्ट समान हैं। सभी कार्यों की तरह जो लौटते हैं true
या false
, इसे "विधेय कार्य" कहा जा सकता है, लेकिन यह सिर्फ शब्दावली है। मुख्य बिंदु यह है कि makeSymmDiffFunc
एक फ़ंक्शन के साथ कॉन्फ़िगर किया गया है जो दो वस्तुओं को स्वीकार करता है और true
अगर हम उन्हें नहीं मानते हैं तो रिटर्न देता है false
।
इसका उपयोग करते हुए, makeSymmDiffFunc
("सममित अंतर फ़ंक्शन को पढ़ें") हमें एक नया फ़ंक्शन देता है:
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
यह वह फ़ंक्शन है जिसका हम वास्तव में उपयोग करेंगे। हम इसे दो सूचियों को पास करते हैं और यह तत्वों को पहले नहीं दूसरे में पाता है, फिर दूसरे में नहीं पहली बार इन दो सूचियों को मिलाता है।
इसे फिर से देखते हुए, हालांकि, मैं निश्चित रूप से आपके कोड से एक क्यू ले सकता था और उपयोग करके मुख्य फ़ंक्शन को थोड़ा सरल किया some
:
var makeSymmDiffFunc = (function() {
var complement = function(pred, a, b) {
return a.filter(function(x) {
return !b.some(function(y) {return pred(x, y);});
});
};
return function(pred) {
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
};
}());
complement
विधेय का उपयोग करता है और अपनी पहली सूची के तत्वों को उसके दूसरे में नहीं लौटाता है। यह एक अलग contains
फ़ंक्शन के साथ मेरे पहले पास की तुलना में सरल है ।
अंत में, मुख्य कार्य को आंतरिक कार्य समारोह को वैश्विक दायरे से बाहर रखने के लिए एक तुरंत लागू फ़ंक्शन अभिव्यक्ति ( IIFE ) में लपेटा जाता है complement
।
अद्यतन, कुछ साल बाद
अब जब ES2015 बहुत अच्छी तरह से सर्वव्यापी बन गया है, तो मैं एक ही तकनीक का सुझाव दूंगा, जिसमें बहुत कम बॉयलरप्लेट हो:
const diffBy = (pred) => (a, b) => a.filter(x => !b.some(y => pred(x, y)))
const makeSymmDiffFunc = (pred) => (a, b) => diffBy(pred)(a, b).concat(diffBy(pred)(b, a))
const myDiff = makeSymmDiffFunc((x, y) => x.value === y.value && x.display === y.display)
const result = myDiff(a, b)
//=> {value="a63a6f77-c637-454e-abf2-dfb9b543af6c", display="Ryan"}