Básicamente, estoy tratando de evitar que se creen objetos duplicados iterando a través de la matriz myLibrary. Si la entrada del usuario es un título único, agregue a la matriz. Si no, denegar la entrada.
No importa lo que intente, llego al punto en que mi código me dice que existe un duplicado pero aún agrega el objeto duplicado.
Obviamente soy nuevo en esto. Gracias de antemano por cualquier ayuda.
let myLibrary = []; class BookInfo { constructor(title, author, pages, genre) { this.title = title, this.author = author, this.pages = pages, this.genre = genre }; }; // Add new book to library array: const addBook = function() { let title = document.getElementById("title"); let author = document.getElementById("author"); let pages = document.getElementById("pages"); let genre = document.getElementById("genre"); document.getElementById("Submit").addEventListener('click', (e) => { e.preventDefault(); const newBook = new BookInfo(title.value, author.value, pages.value, genre.value); if (myLibrary.length === 0) { myLibrary.push(newBook); // Add first book to library. alert(`${title.value} has been added to your library!`); document.querySelector('form').reset(); // clear form after submit. } else { myLibrary.forEach(book => { console.log(newBook.title); if (book.title === newBook.title) { // Dup exists. alert(`${title.value} already exists in your library.`); document.querySelector('form').reset(); // clear form after submit. return; } else { myLibrary.push(newBook); alert(`${title.value} has been added to your library.`); document.querySelector('form').reset(); // clear form after submit. return; } }) }; }); }; addBook(); <form> <input type="text" id="title"> <input type="text" id="author"> <input type="number" id="pages"> <input type="text" id="genre"> <input type="button" value="Submit" id="Submit"> </form>El método integrado "forEach" de Array.prototype no se interrumpirá con "romper" o "regresar" https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach (mira el primer cuadro de nota azul)
En su caso, puede iterar usando un bucle for
for (let i = 0; i < myLibrary.length; i++) { if (myLibrary[i].title === book.title) { break; } else if (i == myLibrary.length - 1) { myLibrary.push(book); } }(en lugar de "myLibrary.forEach")
O puede agregar siempre y limpiar la duplicación después de eso:
myLibrary = myLibrary.filter( (i, idx) => myLibrary.findIndex((j) => i.title === j.title) === idx );Está recorriendo la matriz y para cada elemento, si no coincide con el elemento que se va a insertar, entonces se inserta el elemento. El problema lógico con esto es que esto agregará el nuevo elemento tantas veces como se hayan encontrado errores de coincidencia en la matriz, independientemente de si el elemento ya está en la matriz. En lugar de su enfoque, estoy usando filter , que es una función que devuelve el subconjunto de la matriz que coincide con la condición. En nuestro caso la condición es que coincida. Entonces, si hay coincidencias, este subconjunto no estará vacío y, por lo tanto, su length será diferente de 0. Entonces, comparo la length con 0 y, si es 0, significa que es un elemento nuevo y se puede insertar. En ese caso, lo envío a myLibrary , notifico que se agregó, restablezco el form y muestro el contenido actual en un div . Esta visualización no es necesaria, pero fue útil en este ejemplo, por lo que podemos saber si funciona correctamente.
Si la length no es 0, entonces estoy alertando que es un duplicado y no hago nada más, ni siquiera reset (porque en el caso de un error tipográfico no es realmente fácil de usar si el usuario sería castigado por tener que ingrese todo de nuevo.)
let myLibrary = []; class BookInfo { constructor(title, author, pages, genre) { this.title = title, this.author = author, this.pages = pages, this.genre = genre }; }; // Add new book to library array: const addBook = function() { let title = document.getElementById("title"); let author = document.getElementById("author"); let pages = document.getElementById("pages"); let genre = document.getElementById("genre"); document.getElementById("Submit").addEventListener('click', (e) => { e.preventDefault(); if (myLibrary.filter(item => item.title === title.value).length === 0) { myLibrary.push(new BookInfo(title.value, author.value, pages.value, genre.value)); alert("added"); document.querySelector("form").reset(); document.querySelector('div').innerText = JSON.stringify(myLibrary); } else { alert("duplicate"); } }); }; addBook(); <form> <input type="text" id="title" placeholder="title"><br> <input type="text" id="author" placeholder="author"><br> <input type="number" id="pages" placeholder="pages"><br> <input type="text" id="genre" placeholder="genre"><br> <input type="button" value="Submit" id="Submit"> </form> <div></div>No puede saber en la primera iteración si el título del libro es nuevo. Para eso, primero debe completar todas las iteraciones.
Pero, ¿por qué no usar una estructura de datos diferente para la biblioteca, una que esté codificada por título? Entonces no necesita ninguna iteración en absoluto.
let myLibrary = {}; // Different structure. class BookInfo { constructor(title, author, pages, genre) { this.title = title; this.author = author; this.pages = pages; this.genre = genre; }; } let title = document.getElementById("title"); let author = document.getElementById("author"); let pages = document.getElementById("pages"); let genre = document.getElementById("genre"); document.getElementById("Submit").addEventListener('click', (e) => { e.preventDefault(); if (Object.hasOwn(myLibrary, title.value)) { alert("duplicate"); } else { myLibrary[title.value] = new BookInfo(title.value, author.value, pages.value, genre.value); alert("added"); document.querySelector("form").reset(); document.querySelector('div').innerText = JSON.stringify(myLibrary); } }); <form> <input type="text" id="title" placeholder="title"><br> <input type="text" id="author" placeholder="author"><br> <input type="number" id="pages" placeholder="pages"><br> <input type="text" id="genre" placeholder="genre"><br> <input type="button" value="Submit" id="Submit"> </form> <div></div>