2013-02-19 15 views
5

Ich habe zwei Arrays, alte und neue, die Objekte an jeder Position halten. Wie würde ich synchronisieren oder das Delta finden (also das, was neu ist, aktualisiert und von dem neuen Array gelöscht gegenüber dem alten Array)JavaScript sync zwei Arrays (von Objekten)/Delta finden

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"} 
]; 

Mit den obigen Daten-ID als Schlüssel, würden wir feststellen, dass Item mit ID = 2 hat einen aktualisierten Titel, Item mit ID = 3 wird gelöscht und Item mit ID = 4 ist neu.

Gibt es dort eine vorhandene Bibliothek, die nützliche Funktionen hat, oder ist es ein Fall von Schleife und innerer Schleife, vergleiche jede Zeile ... z.

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  
    } 
} 

Machen Sie diese Art von Vergleich dreimal, um neue, aktualisierte und gelöschte zu finden?

+1

Sie die Dinge beschleunigen könnte ein wenig, wenn die IDs eindeutig sind und Sie ein Objekt mit dem id als Schlüssel. – Sirko

+0

Sie sollten erklären, was die Ausgabe ist? Ein Objekt mit drei Eigenschaften? '{hinzugefügt: 4], geändert: [2], gelöscht: [3]}' –

+0

Die Ausgabe wäre wahrscheinlich in drei Arrays am besten. Die gelöschten müssten nur IDs, hinzugefügt und geändert würde die vollständige "Zeile"/Objekt – Fergal

Antwort

12

Es gibt keine Magie zu tun, was Sie brauchen. Sie müssen beide Objekte durchlaufen, um nach Änderungen zu suchen. Ein guter Vorschlag ist, Ihre Struktur in Karten für schnellere Suchen umzuwandeln.

/** 
* 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); 

Siehe http://jsfiddle.net/wjdZ6/1/ für ein Beispiel

+0

Danke, erspart mir zu viel Nachdenken;) – Fergal

+1

@Fergal Das ist keine gute Sache, das Beste für dich wäre es, es selbst zu versuchen und dann Fragen zu stellen, wenn du es nicht zur Arbeit bringen kannst. Wenn Sie es zur Arbeit bringen können, aber Vorschläge wünschen, dann können Sie fragen, http://codereview.stackexchange.com/ –

+1

Nun, ich war ein bisschen Spaß. Ich habe es versucht und habe es am meisten funktioniert (ein paar mehr Zeilen erforderlich ist alles), während Sie diese Seite im Auge behalten. Aber die Art und Weise, wie Sie die Arrays in Objekte umgewandelt haben, hat die Codezeilen wirklich reduziert (mit hasOwnProperty) – Fergal

0

Dies ist Typoskript Version von @Juan Mendes Antwort

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; 
    } 
Verwandte Themen