2014-11-02 14 views
7

Wie kann ich ein Element im Array aktualisieren/hinzufügen?Wie aktualisiere/füge Element des Arrays in JavaScript hinzu?

var persons = { 
    data: [] 
}; 

var bob = {name: 'Bob', age: 15}; 
var fill = {name: 'Fill', age: 20}; 
var mark = {name: 'Mark', age: 19}; 
var john = {name: 'John', age: 4}; 

persons['data'].push(bob); 
persons['data'].push(fill); 
persons['data'].push(mark); 
persons['data'].push(john); 

var updatedJohn = {name: 'John', age: 100}; 

if (!persons['data'][updatedJohn.name]){ 
    persons['data'].push(updatedJohn); 
} else { 
    persons['data'][updatedJohn.name] = updatedJohn; // this line doesn't work 
} 

Ich kann nicht herausfinden, wie ein Element des Arrays zu aktualisieren, wenn Element John bereits vorhanden ist.

UPDATE

jsFiddle example

+0

Was passiert, wenn zwei Personen den gleichen Namen haben? – axelduch

+0

In diesem Fall müssen wir eine existierende Person (John) aktualisieren. Dieses Array ist wie ein 'Set'. – Alex

Antwort

4

Sie benötigen eine Abfragefunktion wie die folgende, damit Sie Indizes nach einer Eigenschaft in Ihrer Datenbank finden können: (JSFiddle)

function getIndexByProperty(data, key, value) { 
    for (var i = 0; i < data.length; i++) { 
     if (data[i][key] == value) { 
      return i; 
     } 
    } 
    return -1; 
} 

var johnIndex = getIndexByProperty(persons.data, 'name', 'John'); 
if (johnIndex > -1) { 
    persons.data[johnIndex] = updatedJohn; 
} else { 
    persons.data.push(updatedJohn); 
} 

Beachten Sie, dass dies nur den ersten Datensatz mit dem Namen John zurückgibt. Sie müssen entscheiden, was Sie im Falle mehrerer solcher Aufzeichnungen tun wollen - alle aktualisieren? Diese Art von Problem besteht darin, dass Datenbanken normalerweise eindeutige Schlüssel zur Identifizierung von Datensätzen haben.

1

Arrays in JavaScript sind durch Zahlen indiziert (oder zumindest sein sollte).

persons['data'].push(bob); 
persons['data'].push(fill); 
persons['data'].push(mark); 

persons[2] verwenden würden Sie {name: 'Mark', Alter: 19}.

Während Javascript ist so flexibel, dass Sie tun können, wie in @Sasa beantworten und String-Indizes verwenden, können Sie von anderen Entwicklern Kniescheiben, wenn Sie tun, da dies eine sehr schlechte Praxis ist.

[ADDED] Betrachten Sie diese Beispiele für seltsame und unerwartetes Verhalten:

var ary = []; 
ary[0] = false; 
ary['using string indexes in javascript arrays is stupid'] = true; 
console.log('pop should return the last added element', ary.pop()); // false - WTF? 
console.log('lastIndexOf should be 1?', ary.lastIndexOf(true)); // -1 WTF? 

Arrays in Javascript sollte als Stapel verwendet werden. Denken Sie an einen Stapel Karten, Sie fügen entweder hinzu (drücken) oder nehmen Karten weg (ziehen), aber Sie wissen nicht, welche Karte wo ist (es sei denn, Sie betrügen).

Wenn Sie eine Liste von Personen mit Namen möchte Sie ein Objekt speichern Personen verwenden:

persons.data = {}; 
persons['data']['Bob'] = bob; 

Oder alternativ können Sie das Array filter Werte zu erhalten, die ein Prädikat entsprechen:

bob = persons.data.filter(function(person){ 
    return person["name"] === 'Bob'; 
})[0]; 

EDIT:

Example eine Funktion, die eine Person würde erstellen oder finden:

var persons = { data : [] } 
persons.data.push({ name: 'Bob', age: 10 }) 

// returns the index of the newly added person 
persons.addOrReplace = function(new_person, attr) { 

    var attr = attr || 'name'; 
    var data = this.data;  
    for (var i = 0; i < data.length; i++) { 
     if (data[i][attr] === new_person[attr]) { 
     data[i] = new_person; 
     return i; 
     } 
    } 
    return this.data.push(new_person); 
} 

persons.addOrReplace({ name: 'Bob', age: 11 }); 
console.log(persons.data.length); // 1 
console.log(persons.data[0].age); // 11 

persons.addOrReplace({ name: 'Joe', age: 11 }); 
console.log(persons.data.length); // 2 
console.log(persons.data[persons.data.length -1].name); // Joe 
+0

Der Grund, warum dies sehr schlechte Praxis ist, ist, dass, da Sie Objekte haben, die für Wörterbücher perfekt geeignet sind (Schlüssel-Wert, auch bekannt als Hashes oder assoziative Arrays) erwarten wir Arrays numerisch durch die Reihenfolge der Insertion indiziert werden. – max

+0

Wenn Sie die Methode 'filter' verwenden, versuchen Sie, den Datensatz mit' bob = updatedBob' zu ändern, der Datensatz in 'persons.data' wird nicht aktualisiert. – Stuart

+0

@ Stuart. Sie liegen falsch, das Objekt wird als Referenz übergeben. http://jsfiddle.net/4xp02cuu/ – max

2

Warum nicht ein assoziatives Array für persons['data'] verwenden, da .push() nur Index-Arrays verwendet

var persons = { 
    data: {} 
}; 

... 
persons['data'][john.name] = john; 
... 

var updatedJohn = {name: 'John', age: 100}; 

// if statement isn't neccesary no more bc 
// if the index is there it will override it and if not 
// it will create a new index 
persons['data'][updatedJohn.name] = updatedJohn; 

Die Linie nicht für Sie arbeiten, weil die Person Array von ganzen Zahlen persons['data'].push() anstelle von Strings indiziert wurde persons['data'][stringIndex]

+0

Warum unten abstimmen ohne Begründung? –

+0

Die Verwendung von "assoziativen Arrays" in Javascript ist eine schlechte Idee, da jeder erwartet, dass Arrays numerisch indiziert werden. Verwenden Sie Objekte, wenn Sie einen Schlüssel/Wert-Speicher wünschen. – max

+0

@papirtiger Ich weiß nicht, wer dir das beigebracht hat, aber assoziierte Arrays (Objekte) sind sehr nützlich in jeder Sprache, nicht nur in js. Warum sollte ich erwarten, dass ein Array, das ich mit assoziierten Schlüsseln erstellt habe, numerisch ist? –

1

Versuchen Sie, durch die Elemente des Objekts persons zu iterieren, aktualisieren Sie das Element, wenn ein Mitglied mit dem gleichen Namen existiert, wenn nicht, schieben Sie ein neues Element in das Array.Verwenden Sie eine neue Variable exists, um zu überprüfen, ob das Element vorhanden ist. Hier

ist das, was Sie tun können:

var persons = { 
    data: [] 
}; 

var bob = {name: 'Bob', age: 15}; 
var fill = {name: 'Fill', age: 20}; 
var mark = {name: 'Mark', age: 19}; 
var john = {name: 'John', age: 4}; 

persons['data'].push(bob); 
persons['data'].push(fill); 
persons['data'].push(mark); 
persons['data'].push(john); 

var updatedJohn = {name: 'John', age: 100}; 

var exists = 0; 

for (var i=0; i<persons['data'].length; i++) { 
    if (persons['data'][i].name == updatedJohn.name) { 
     persons['data'][i].age = updatedJohn.age; 
     exists = 1; 
    } 
} 

if (exists === 0) 
    persons['data'].push(updatedJohn); 

Hier wird Sie aktualisiert Geige: http://jsfiddle.net/t4kjgkcn/3/

+0

wird nicht funktionieren, wie es steht – Stuart

+0

@Stuart können Sie klären? Ich habe es hier getestet und es funktionierte für mich: http://jsfiddle.net/95d9oLkq/1/ – webeno

+0

probiere 'console.log (persons.data)' - Du hast ein Duplikat von 'updateJohn' in die Datenbank für jedes existierende hinzugefügt Aufnahme, die nicht den Namen "John" hatte – Stuart

1

Sie eine Lookup-Tabelle für jede existierende Person machen kann, wenn es nicht in ihr, Sie schieben Sie es in Personen .data und erstellen Sie einen neuen Eintrag in der Nachschlagetabelle, sonst schreiben Sie das Personenobjekt vollständig um, ohne die angegebene Referenz zu brechen. (Ich habe einen Kommentar geschrieben, um diesen Teil zu erklären).

JSFiddle here

var persons = { 
    data: [] 
}; 

var bob = {name: 'Bob', age: 15}; 
var fill = {name: 'Fill', age: 20}; 
var mark = {name: 'Mark', age: 19}; 
var john = {name: 'John', age: 4}; 

persons['data'].push(bob); 
persons['data'].push(fill); 
persons['data'].push(mark); 
persons['data'].push(john); 

var personsHash = {}; 

// store an external reference for each persons 
for (var i = 0, l = persons.data.length; i < l; i++) { 
    personsHash[persons.data[i].name] = persons.data[i]; 
} 

var updatedJohn = {name: 'John', age: 100}; 

if (!personsHash[updatedJohn.name]){ 
    personsHash[updatedJohn.name] = updatedJohn; 
    persons['data'].push(updatedJohn); 
} else { 
    var key; 
    var person = personsHash[updatedJohn.name]; 
    // comment if you don't want a full rewrite but just an update of attributes 
    /**/ 
    for (key in person) { 
     delete person[key]; 
    } 
    /**/ 
    for (key in updatedJohn) { 
     if (updatedJohn.hasOwnProperty(key)) { 
      person[key] = updatedJohn[key]; 
     } 
    } 
} 
+0

Ich brauche keinen brandneuen John hinzuzufügen, wenn der alte John existiert. In diesem Fall muss ich nur den alten John durch einen neuen John ersetzen. Das ist alles. Aber Ihre Lösung fügt das neue John-Objekt hinzu. – Alex

+0

Ja, es wird nur hinzugefügt, wenn es nicht existiert.Ich habe gerade einen Weg benutzt, der den alten John komplett umschreibt, aber niemals die Referenz des Objekts bricht (indem ich '=' nicht verwende) – axelduch

+0

http://jsfiddle.net/9x4vv7vq/3/ – Alex

0

function addOrUpdate(arr, comp, update) { 
 
    if (arr) { 
 
    var updated = false; 
 
    arr.map(function(e, i) { 
 
     var found = e[comp] == update[comp]; 
 
     if (found) { 
 
     angular.extend(arr[i], update); 
 
     updated = true; 
 
     } 
 
    }); 
 
    if (!updated) { 
 
     arr.push(update); 
 
    } 
 
    } 
 
} 
 

 
//example 
 

 
var a = [{ 
 
    id: 1, 
 
    name: 'a' 
 
}, { 
 
    id: 2, 
 
    name: 'b' 
 
}, { 
 
    id: 3, 
 
    name: 'c' 
 
}]; 
 

 
addOrUpdate(a, "id", { 
 
    id: 4, 
 
    name: 'e3333' 
 
}); 
 
//looks for an elemnent with id=4, doesnt find, and adds it 
 

 
addOrUpdate(a, "id", { 
 
    id: 4, 
 
    name: 'e5555' 
 
}); 
 
//this time it will find and update the name

Verwandte Themen