Removing a targeted element from an array in JavaScript

I recently developed a small program that allows users to enter the name of a book along with its ISBN code. Everything was working perfectly until I added a feature to delete books based on their ISBN. While the deletion process works fine, I noticed that the alert message incorrectly states that the book does not exist in the database for every book stored.

For instance, if I have 5 books saved and I try to delete the one with the ISBN "12121" (which is the 4th object in the array), the function first returns false for the first 3 objects, then true for the 4th object, and finally false for the last object in the array.

Is there a way to modify the function so it only targets the object with the specified ISBN without checking each entry in the array?

var books = [];
books.push({
    bookName: "GameOfThrones",
    isbn: "12345",
});
function deleteBook(){
    var bookToDelete = prompt("Enter the ISBN of the book you want to delete");
    for(var i=0; i<books.length; i++){
        if (books[i].isbn == bookToDelete){
            books.splice(i, 1);
            alert("The book has been successfully deleted");
            break;
        }
    }
    for (var i=0; i<books.length; i++){
        document.write(books[i].isbn + " - " + books[i].bookName + "<br/>");
    }
}

Answer №1

If you opt to select elements randomly from an array, you'll need to search through each element. Another approach is to utilize a hash map or sort the array and employ the binary search algorithm. Personally, I wouldn't focus on premature optimization unless your array is exceptionally large (on the scale of hundreds of thousands of elements).

On another note, your initial code can be refactored more efficiently by utilizing the Array filter function.

    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.

Answer №2

If you come across the book you are looking for in a for loop, simply return at that point. However, if the book happens to be at the end of the array, you would still have to search through the entire array.

One way to improve this is by using a sorted array, as it can give you an idea of where to start your search. But a more efficient solution would be to use a Hash table instead of an array.

An easy implementation would involve creating a Hash table like this:

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

Then, if you want to remove a book from the table, you can do so directly using delete:

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

Answer №3

If you're looking for a simple solution using your example, consider using the break statement within a for loop to stop processing once the desired item is found:

 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/>");
     } 
}

For browsers other than IE, you can consider using Array.findIndex instead of a traditional for loop. Here's a reference link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

Here's an alternative approach:

var index = book.findIndex(function (element) { return element.isbn == book1 });

Answer №4

When filtering an array, you have the option to retrieve all items that do not match certain criteria. In this process, you can also keep track of whether a specific item was found. This allows you to execute additional actions, such as removing it from the database.

While it is possible to include database operations within the filter function, separating them into distinct blocks makes the code more readable and maintainable. This explains why there is an if-block after the filter statement.

The example below illustrates these concepts, utilizing a textarea for output instead of the console. The purpose is to showcase how to display content in an HTML element using the textContent property.

Example:

document.addEventListener("DOMContentLoaded", onLoad);

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

function deleteBook(isbn) {
  // utilize passed-in ISBN or retrieve from input field
  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 the database...\n`;
      return false;
    } else
      return isbn != book.isbn;
  });

  // handle any subsequent actions
  if (book_found) {
    debug.textContent += `New List (excluding ${isbn}):\n`;
    outputBooks(books);
  } else
    debug.textContent += `Book (ISBN: ${isbn}) could not be found!\n\n`;
}

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

// Ensure the debug element is present 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Python Error: Trying to access an index that does not exist in

Currently working on solving the TwoSum problem using Python. I've been trying out the two pointer approach, where one pointer starts at the beginning and the other at the end of the array. When the sum of the values at the two indexes is greater than ...

Several different references within a linear array

Recently, I've been delving into various sources to implement strongly connected algorithms. While doing so, I came across a particular tutorial that left me perplexed at The specific line causing my confusion reads as follows: if (used[v[s][i]] == ...

Luxon DateTime TS Error: The 'DateTime' namespace cannot be used as a type in this context

I have encountered an issue while trying to set the type of a luxon 'DateTime' object in TypeScript. The error message DateTime: Cannot use namespace 'DateTime' as a type appears every time I attempt to assign DateTime as a type. Below ...

How can I remove a row from an MVC webgrid using an ajax call?

Within my MVC Razor view, I have a partial view containing webgrid data. My goal is to include an action link to delete a specific row of data. To accomplish this, I crafted the following JavaScript function: function delMeal(pid) { if (confirm("Do yo ...

Sustaining the Status of a Changeable Form Element

To fulfill the requirement of constructing a Form Builder component that generates forms based on JSON data from the backend, I have identified 7 types of input fields that may be encountered: email password select file date input of type text input of ty ...

Sending a JSON response back to an AJAX request triggers a file download that includes the response

When submitting a form using jQuery ajax, the server returns a json response. However, rather than parsing the json result, the browser prompts me to download the json response. I've encountered this problem in the past when I forgot to return false ...

jqxChart displaying data with proportions

Exploring the waterfall series feature of the jqxChart was quite interesting. As per its API, the code snippet below is used to set the values of the y-axis: valueAxis: { title: {text: 'Population<br>'}, unitInterval: 1000000, ...

Enhance D3 Version 6 Stacked Bar Chart with Spacing and Interactive Features

My bar chart lacks the spacing between bars that I intended to achieve, and the interactive tooltip doesn't show up when hovering over the bars. I could use some assistance with this. The purpose is to display the value of a specific color when hoveri ...

Disable automatic playback once the page has loaded (Bootstrap carousel in Twitter)

I'm having an issue with my slider not autoplaying after the page loads. However, when I right-click, autoplay seems to turn on. What could be causing this problem? $('#myCarousel').on('slid', '', function() { var $t ...

Creating dynamic form groups that allow for the addition and removal of forms while assigning unique identifiers and names to each input field

I am currently immersed in the development of a sophisticated CMS system. My main objective is to dynamically add and remove form inputs using JavaScript upon clicking a button, with the ultimate goal of submitting the data into a database via PHP script. ...

Expanding the length of a byte array in Java

As I work with a Spring multipart controller, I'm facing an issue when trying to upload files ranging from 2GB to 5GB. The problem arises when using file.getBytes(), with the error message indicating that the required array length is too large. It se ...

Issues with Knockout functionality due to retrieval of values from an external JSON file

Attempting to manipulate formulas in a spreadsheet-like fashion using knockout appears to be causing some issues with functionality. The data in question is sourced from an external Json file. Json file { "info": [ { "Name":"Newb ...

How to empty an array once all its elements have been displayed

My query pertains specifically to Angular/Typescript. I have an array containing elements that I am displaying on an HTML page, but the code is not finalized yet. Here is an excerpt: Typescript import { Component, Input, NgZone, OnInit } from '@angul ...

I'm having trouble locating the corresponding end tag for "<%". How can I resolve this issue?

Here lies the issue: <% for(let i = 0; i < <%= elements %>.length; i++){ %> <li><%= elements[i] %></li> <%}%> ...

Postal Code Auto-Suggest by Google

I'm attempting to create a unique autocomplete feature for a text box that specifically provides postal codes. To accomplish this, I have followed the guidelines outlined in the documentation found at https://developers.google.com/places/webservice/au ...

The Bootstrap table remains unresponsive despite using the .table-responsive class

I have created a bootstrap table but I am facing an issue with the horizontal scroll on mobile devices. Even after adding the table-responsive class to the element with the .table class, it is not working as expected. <div class="table-responsive t ...

Combining three Char** arrays into a single static array

With three dynamically allocated arrays of char** type, the question arises - how can they be added to a single static array? Is it necessary to use a char*** array? void combineArrays(char ***array[3], int *limit) { int i; //loop control for (i ...

Encountering difficulty in Jade Template when trying to incorporate a file using a relative

Whenever I try to include a file from the same folder, I keep getting this error message: "filename" option is necessary for using "include" with "relative" paths There are two files in the folder: index.jade list_of_items.jade .content-container ...

Using PHP to Populate an Array in Android for Setting Text

Here is the java code snippet I am working with: @Override protected void onPostExecute(String products) { this.inv_title.setText(products); } I am facing an issue where the String products that I receive from the PHP server is actually an array. Whe ...

Executing a function when a tag is deleted using ngInputTags in AngularJS

Is there a way to trigger a function when removing a tag? I've attempted different approaches without success. Any suggestions on how to achieve this? <tags-input ng-model="vm.studentObj.assigned_employees" display-property="name" > </tags-i ...