Удалить конкретный элемент из массива - JavaScript

Я хотел создать небольшую программу, в которой вы вводите имя книги и ее код isbn, с некоторыми другими вещами, и она работала просто отлично, пока я не захотел создать приглашение, которое спрашивает меня, какую книгу я хочу удалить (по ISBN). Это на самом деле работает нормально; Когда я записываю isbn книги, которую я сохранил в массиве, она удаляет эту книгу, и она isbn, но предупреждение уведомляет меня о том, что книга не существует в базе данных (не добавлена ​​ранее) для каждой книги, которую я сохранил.

Например, у меня хранится 5 книг, одна из которых (4-й объект в массиве) с ISBN-кодом "12121", и я хочу удалить эту из массива. Функция возвращает меня false для первых 3 объектов в массиве (alert ("Книга с таким ISBN не существует в нашей базе данных.")), Затем она возвращает true для 4-го объекта, а затем возвращает мне false также для последнего объекта в массив.

Как мне сделать функцию, которая только выбирает (а затем удаляет) объект с ISBN, который я поместил туда в окне подсказки, не проверяя каждый из объектов внутри массива?

    var book = [];
book.push({
    bookName: "GameOfThrones",
    isbn: "12345",
});
function deleteBook(){
    var book1 = prompt("Enter the ISBN of the book you want to delete");
    for var(i=0; i<book.length; i++){
        if (book[i].isbn == book1){
            book.splice(i, 1);
            alert("Book is successfully deleted");
        }
        else{
            alert("Book with that ISBN doesn't exist in our database.");
        }
    }
    for (var i=0; i<book.length; i++){
        document.write(book[i].isbn + " - " + book[i].bookName + "<br/>");
    }
}

4 ответа

Если вы решите использовать массив элементов в произвольном порядке, то нет необходимости просматривать каждый элемент. Другой вариант - использовать хеш-карту или отсортировать массив и использовать алгоритм двоичного поиска. Лично я не стал бы беспокоиться о такой преждевременной оптимизации, если бы ваш массив не был очень большим (порядка ста тысяч элементов).

Кроме того, ваш исходный код может быть написан намного чище, если вы используете функцию фильтра Array.

    var books = [];
    books.push({
        bookName: "GameOfThrones",
        isbn: "12345",
    });

    var ISBNToDelete = prompt("Enter the ISBN of the book you want to delete");

    function deleteBookByISBN(isbn, books) {
        var newBooks = books.filter(function(book) {
           return book.isbn !== isbn;
        });
        if (newBooks.length != books.length) {
             alert("Book successfully deleted")  
        } else {
             alert("Book with that ISBN doesn't exist in our database.");
        }
        return newBooks;
    }
    books = deleteBookByISBN(ISBNToDelete, books); // reassign the new set of books to books.

Если ты filter в массиве вы можете вернуть все книги, которые не совпадают. Во время этого процесса вы можете сохранить логическое значение, если книга была найдена. Используя это логическое значение, вы можете выполнять другие действия (например, удалять его из базы данных).

Вы можете выполнить эти действия базы данных внутри filter, но для того, чтобы код легче было отслеживать и поддерживать, хорошо разделить его. Вот почему есть if блок после filter,

Следующий пример демонстрирует эту концепцию выше. Он также использует текстовую область для регистрации, в отличие от консоли. Это должно служить демонстрацией того, как выводить на элемент HTML с помощью textContent имущество.

Пример:

document.addEventListener("DOMContentLoaded", onLoad);

var books = [{
  bookName: "GameOfThrones",
  isbn: "12345"
}, {
  bookName: "Jurrasic Park",
  isbn: "98765"
}, {
  bookName: "Westworld",
  isbn: "33333"
}];


function deleteBook(isbn) {
  // use isbn passed in, or look it up
  isbn = isbn || document.getElementById('isbn').value;

  var book_found = false;
  books = books.filter((book, i) => {
    if (book.isbn == isbn) {
      book_found = true;
      debug.textContent += `Deleting "${book.bookName} from database...\n`;
      return false;
    } else
      return isbn != book.isbn;
  });

  // handle any follow-up actions
  if (book_found) {
    debug.textContent += `New List (w/o ${isbn}):\n`;
    outputBooks(books);
  } else
    debug.textContent += `Book (isnb:${isbn}) could not be found!\n\n`;
}


// Used for Logging Output (in place of console)
function outputBooks(books) {
  books.forEach(book => {
    debug.textContent += ['  ' + book.isbn, book.bookName].join(': ') + '\n'
  });
  debug.textContent += '\n';
}


// Ensures the debug element is on the page
function onLoad(event) {
  // Default
  window.debug = document.getElementById('debug');
  debug.textContent += 'Starting List:\n';
  outputBooks(books);
}
textarea {
  height: 20em;
  width: 80%;
  display: block;
}

.block {
  display: block;
}
<label>ISBN: 
   <input id="isbn" type="text" />
</label>
<button type="button" class="delete" onclick="deleteBook()">Delete</button>

<label><span class="block">Debug:</span>
  <textarea id="debug" disabled></textarea>
</label>

Вы можете просто вернуться из-за заявления в тот момент, когда вы нашли свою книгу. Проблема в том, что когда book находится в конце массива, в этом случае вы все равно пройдете через весь массив.

Сортированный массив может вам немного помочь (вы бы точно знали, где искать книгу), но лучшее, что нужно сделать, это отбросить массив и выбрать какую-нибудь хэш-таблицу.

Простая реализация будет:

var books = {};
books['UniqueISBN'] = {name: "Where is the sun", author: "Unknown"};

Затем вы можете удалить его напрямую, используя delete;

var id = 'UniqueISBN';
delete books[id];

Самый простой способ с вашим примером использовать break заявление о прекращении обработки for Цикл, как только вы нашли элемент:

 function deleteBook(){
     var book1 = prompt("Enter the ISBN of the book you want to delete");
     for (var i=0,count=book.length; i<count; i++){
         if (book[i].isbn == book1){
             book.splice(i, 1);
             alert("Book is successfully deleted");
             break;
         }
         else{
             alert("Book with that ISBN doesn't exist in our database.");
         }
     }
     for (var i=0; i<book.length; i++){
         document.write(book[i].isbn + " - " + book[i].bookName + "<br/>");
     } 
}

Я не знаю, на какие браузеры вы ориентируетесь, но если это не IE, вы можете исключить цикл for и использовать Array.findIndex вместо этого: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

Что-то вроде:

var index = book.findIndex(function (element) { return element.isbn == book1 });
Другие вопросы по тегам