Saya mengambil pendekatan dengan tujuan yang sedikit lebih umum, meskipun memiliki kesamaan ide dengan pendekatan @Cerbrus dan @Kasper Moerch . Saya membuat fungsi yang menerima predikat untuk menentukan apakah dua objek sama (di sini kita mengabaikan $$hashKeyproperti, tetapi bisa jadi apa saja) dan mengembalikan fungsi yang menghitung perbedaan simetris dari dua daftar berdasarkan predikat itu:
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"}
Ia memiliki satu keuntungan kecil dibandingkan pendekatan Cerebrus (seperti halnya pendekatan Kasper Moerch) karena ia lolos lebih awal; jika menemukan kecocokan, tidak perlu repot memeriksa daftar lainnya. Jika saya punyacurry fungsi yang berguna, saya akan melakukan ini sedikit berbeda, tetapi ini berfungsi dengan baik.
Penjelasan
Sebuah komentar meminta penjelasan yang lebih detail untuk pemula. Ini usahanya.
Kami meneruskan fungsi berikut ke makeSymmDiffFunc:
function(x, y) {
return x.value === y.value && x.display === y.display;
}
Fungsi ini adalah bagaimana kita memutuskan bahwa dua objek itu sama. Seperti semua fungsi yang mengembalikan trueatau false, itu bisa disebut "fungsi predikat", tapi itu hanya terminologi. Poin utamanya adalah yang makeSymmDiffFuncdikonfigurasi dengan fungsi yang menerima dua objek dan mengembalikan truejika kita menganggapnya sama, falsejika tidak.
Menggunakan itu, makeSymmDiffFunc(baca "membuat perbedaan fungsi simetris") mengembalikan kita fungsi baru:
return function(a, b) {
return complement(pred, a, b).concat(complement(pred, b, a));
};
Ini adalah fungsi yang akan kita gunakan. Kami memberikan dua daftar dan menemukan elemen di yang pertama bukan yang kedua, lalu yang kedua bukan yang pertama dan menggabungkan kedua daftar ini.
Namun, memeriksanya lagi, saya pasti bisa mengambil isyarat dari kode Anda dan menyederhanakan fungsi utama sedikit dengan menggunakan 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));
};
};
}());
complementmenggunakan predikat dan mengembalikan elemen dari daftar pertamanya, bukan yang kedua. Ini lebih sederhana daripada pass pertama saya dengan containsfungsi terpisah .
Terakhir, fungsi utama dibungkus dalam ekspresi fungsi yang dipanggil segera ( IIFE ) untuk menjaga complementfungsi internal tetap berada di luar cakupan global.
Perbarui, beberapa tahun kemudian
Sekarang ES2015 telah menjadi cukup baik di mana-mana, saya akan menyarankan teknik yang sama, dengan boilerplate yang jauh lebih sedikit:
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"}