2013-02-19 18 views
5

मेरे पास दो एरे, पुराने और नए हैं, जो प्रत्येक स्थिति पर ऑब्जेक्ट्स रखते हैं। मैं कैसे सिंक या डेल्टा मिलेगा (क्या नया, अद्यतन और पुराने सरणी की तुलना में नई सरणी से हटा दिया जाता यानी)जावास्क्रिप्ट सिंक दो एरे (ऑब्जेक्ट्स)/डेल्टा

var o = [ 
    {id:1, title:"title 1", type:"foo"}, 
    {id:2, title:"title 2", type:"foo"}, 
    {id:3, title:"title 3", type:"foo"} 
]; 

var n = [ 
    {id:1, title:"title 1", type:"foo"}, 
    {id:2, title:"title updated", type:"foo"}, 
    {id:4, title:"title 4", type:"foo"} 
]; 
उपरोक्त डेटा के साथ

, कुंजी के रूप में आईडी का उपयोग कर, हम पाते हैं कि आईडी = 2 के साथ आइटम में एक अद्यतन शीर्षक है, आईडी = 3 के साथ आइटम हटा दिया गया है, और आईडी = 4 के साथ आइटम नया है।

क्या वहां कोई मौजूदा लाइब्रेरी है जिसमें उपयोगी कार्य हैं, या यह लूप और आंतरिक पाश का मामला है, प्रत्येक पंक्ति की तुलना करें ..e.g।

for(var i=0, l=o.length; i<l; i++) 
{ 
    for(var x=0, ln=n.length; x<ln; x++) 
    { 
     //compare when o[i].id == n[x].id  
    } 
} 

नई, अद्यतन और हटाए जाने के लिए इस तरह की तुलना तीन बार करें?

+1

आप बातें, एक छोटे से तेजी लाने सकता है अगर आईडी अद्वितीय हैं और आप आईडी के साथ किसी चीज़ का इस्तेमाल चाबियाँ के रूप में – Sirko

+0

आपको समझा जाना चाहिए कि आउटपुट क्या है? तीन गुणों वाला एक वस्तु? '{जोड़ा गया: 4], बदल गया: [2], हटा दिया गया: [3]}' –

+0

आउटपुट शायद तीन सरणी में सबसे अच्छा होगा। हटाए गए केवल आईडी की आवश्यकता होगी, जोड़ा और बदले में पूर्ण "पंक्ति"/ऑब्जेक्ट – Fergal

उत्तर

12

आपको जो चाहिए वह करने के लिए कोई जादू नहीं है। आपको परिवर्तनों की तलाश में दोनों वस्तुओं के माध्यम से पुन: प्रयास करने की आवश्यकता है। एक अच्छा सुझाव है कि अपनी संरचना को तेजी से खोजों के लिए नक्शे में बदलना है।

/** 
* Creates a map out of an array be choosing what property to key by 
* @param {object[]} array Array that will be converted into a map 
* @param {string} prop Name of property to key by 
* @return {object} The mapped array. Example: 
*  mapFromArray([{a:1,b:2}, {a:3,b:4}], 'a') 
*  returns {1: {a:1,b:2}, 3: {a:3,b:4}} 
*/ 
function mapFromArray(array, prop) { 
    var map = {}; 
    for (var i=0; i < array.length; i++) { 
     map[ array[i][prop] ] = array[i]; 
    } 
    return map; 
} 

function isEqual(a, b) { 
    return a.title === b.title && a.type === b.type; 
} 

/** 
* @param {object[]} o old array of objects 
* @param {object[]} n new array of objects 
* @param {object} An object with changes 
*/ 
function getDelta(o, n, comparator) { 
    var delta = { 
     added: [], 
     deleted: [], 
     changed: [] 
    }; 
    var mapO = mapFromArray(o, 'id'); 
    var mapN = mapFromArray(n, 'id');  
    for (var id in mapO) { 
     if (!mapN.hasOwnProperty(id)) { 
      delta.deleted.push(mapO[id]); 
     } else if (!comparator(mapN[id], mapO[id])){ 
      delta.changed.push(mapN[id]); 
     } 
    } 

    for (var id in mapN) { 
     if (!mapO.hasOwnProperty(id)) { 
      delta.added.push(mapN[id]) 
     } 
    } 
    return delta; 
} 

// Call it like 
var delta = getDelta(o,n, isEqual); 

एक उदाहरण

+0

धन्यवाद, मुझे बहुत कठिन सोचने के लिए बचाता है;) – Fergal

+1

@ फर्गल यह अच्छी बात नहीं है, आपके लिए यह बेहतर चीज है कि आप इसे स्वयं ही कोशिश करें, और फिर सवाल पूछें कि क्या आप इसे काम नहीं कर पाएंगे। यदि आप इसे काम पर ला सकते हैं लेकिन सुझाव चाहते हैं, तो आप http://codereview.stackexchange.com/ –

+1

पर पूछ सकते हैं, ठीक है, मैं मजाक कर रहा था। इस पृष्ठ पर नजर रखने के दौरान मैंने कोशिश की और इसे ज्यादातर काम कर लिया (कुछ और लाइनों की आवश्यकता है)। लेकिन जिस तरह से आपने ऑरे को ऑब्जेक्ट्स में परिवर्तित किया है, वास्तव में कोड की लाइनों को कम कर दिया है (हैऑनप्रॉपर्टी का उपयोग करके) – Fergal

0

के लिए http://jsfiddle.net/wjdZ6/1/ देखें इस @Juan Mendes जवाब का टाइपप्रति संस्करण है

mapFromArray(array: Array<any>, prop: string): { [index: number]: any } { 
    const map = {}; 
    for (let i = 0; i < array.length; i++) { 
     map[array[i][prop]] = array[i]; 
    } 
    return map; 
    } 

    isEqual(a, b): boolean { 
    return a.title === b.title && a.type === b.type; 
    } 

    getDelta(o: Array<any>, n: Array<any>, comparator: (a, b) => boolean): { added: Array<any>, deleted: Array<any>, changed: Array<any> } { 
    const delta = { 
     added: [], 
     deleted: [], 
     changed: [] 
    }; 
    const mapO = this.mapFromArray(o, 'id'); 
    const mapN = this.mapFromArray(n, 'id'); 
    for (const id in mapO) { 
     if (!mapN.hasOwnProperty(id)) { 
     delta.deleted.push(mapO[id]); 
     } else if (!comparator(mapN[id], mapO[id])) { 
     delta.changed.push(mapN[id]); 
     } 
    } 

    for (const id in mapN) { 
     if (!mapO.hasOwnProperty(id)) { 
     delta.added.push(mapN[id]); 
     } 
    } 
    return delta; 
    } 
संबंधित मुद्दे