Determină dacă trebuie să împingă sau să actualizeze obiectul din matrice pe baza ID-ului unic (Revizuirea codului, Javascript, Orientat Pe Obiecte, Matrice)

J. Doe a intrebat.

Încerc să scriu o funcție de bază care să decidă dacă obiectul există deja în matricea de obiecte pe baza id-ului unic care se află în interiorul acestui obiect ca proprietate. În urma căutărilor am găsit acest cod și pare să facă treaba bine, dar îmi imaginez că există o modalitate mai bună și mai rapidă de a determina dacă să împingă sau să actualizeze obiectul. Dacă ați putea împărtăși cel mai bun răspuns pentru acest lucru, vă rog…

var myArray = [
  {
    id: 1,
    car: "Ford"
  },
  {
    id: 2,
    car: "Honda"
  }
];

var objToOverwrite = {
  id: 1,
  car: "Bentley" // to overwrite car: "Ford"
};

var objToPush = {
  id: 3,
  car: "Toyota"
};


function pushToArray ( arr, obj ) {


  var existingIds = arr.map((obj) => obj.id);

    if (! existingIds.includes(obj.id)) {
      arr.push(obj);
    } else {
      arr.forEach((element, index) => {
        if (element.id === obj.id) {
          arr[index] = obj;
        };
      });
    };
};

pushToArray ( myArray, objToPush );

console.log(myArray);

Comentarii

  • Întrebare similară Update if exists or add new element to array of objects – elegant way in javascript + lodash-  > Por Michael Freidgeim.
3 răspunsuri
cbojar

pushToArray funcție este mai puțin eficientă decât ar putea fi, deoarece face o buclă peste întregul array de mai multe ori. Am putea folosi în schimb find()/findIndex() pentru a parcurge în buclă întreaga matrice doar o singură dată:

function pushToArray(arr, obj) {
    const index = arr.findIndex((e) => e.id === obj.id);

    if (index === -1) {
        arr.push(obj);
    } else {
        arr[index] = obj;
    }
}

Această performanță este tot O(n), dar se repetă mai puțin și nu necesită modificarea structurii de date pe care o folosiți.

Dacă aveți nevoie de o performanță mai bună decât aceasta, puteți păstra array-ul sortat după ID și puteți implementa o simplă căutare binară sau puteți schimba structura de date cu una mai optimizată pentru căutări rapide.

Pavel Molchanov

Puteți converti o matrice în hartă și să accesați harta după id, de exemplu:

var myArray = [
  {
    id: 1,
    car: "Ford"
  },
  {
    id: 2,
    car: "Honda"
  }
];

Poate fi convertit în hartă:

var result = myArray.reduce(function(map, obj) {
    map[obj.id] = obj.car;
    return map;
}, {});

Rezultatul va fi:

{
  1:"Ford",
  2:"Honda"
}

Apoi doar atât:

result[obj.id] = obj.car;

Dacă elementul nu a existat, va fi adăugat, dacă există, va fi actualizat.

Blindman67

Dacă știi că există un singur element nu folosi o buclă din care nu poți ieși.

function pushToArray ( arr, obj ) {
    var existingIds = arr.map((obj) => obj.id);
    if (! existingIds.includes(obj.id)) {
        arr.push(obj);
    } else {
        arr.forEach((element, index) => { // You are forced to iterate all items
            if (element.id === obj.id) {
               arr[index] = obj;
            };   // The ; is not needed after } unless its an Object literal
        });  
    }; // again ; not needed
}; // ; not needed

Folosiți o for buclă mai degrabă decât Array.forEach atunci când trebuie să ieșiți din buclă mai devreme.

//...
   var index = 0;
   for (const element of arr) {
       if (element.id === obj.id) {
           arr[index] = obj;
           break;   // found and replaced, nothing more to do so break out of loop
       }
       index ++;
   }

The id este unic, așa că tot ce trebuie să faceți este să obțineți indexul elementului după id. Array.findIndex va face acest lucru pentru dvs. și apoi fie va înlocui un element existent, fie îl va introduce pe cel nou. Astfel, nu va mai fi nevoie să creați un array suplimentar de elemente existente. ids

function pushToArray(arr, obj) {
    const index = arr.findIndex(item => item.id === obj.id);
    if (index > -1) { arr[index] = obj }
    else { arr.push(obj) }
}

Personal, aș stoca datele nu într-o matrice, ci ca un fișier Map Astfel, nu va trebui să faceți nimic altceva decât să setați prin id

// the array as a map with id as the index;
function addItem(map, obj) {
    map.set(obj.id, obj);  // will replace existing if id is already used
                           // or add if the id is not used.
}

Puteți converti din array în hartă după cum urmează

const myMap = new Map();
for (const item of myArray) { myMap.set(item.id, item) };