Having a problem with JavaScript when using the Array.includes() method to test for duplicate items

Utilizing an input connected to an API, I can retrieve a list of cities based on the entered letters. The API is triggered with each keyup event in this manner:

let ville_input = document.getElementById("search_immobilier_ville");
let ville_arr = [];

ville_input.addEventListener("keyup", () => {
  res_list.innerHTML = "";

  fetch("https://api.fr/communes?nom=" + ville_input.value)
    .then(res => {
      return res.json();
    })
    .then(data => {
      data.forEach(el => {
        if (
          el.codeDepartement == "971" &&
          el.nom
            .toUpperCase()
            .startsWith(ville_input.value.toUpperCase().trim())
        ) {
          if (!ville_arr.includes([el.nom, el.codesPostaux[0]])) {
            ville_arr.push([el.nom, el.codesPostaux[0]]);
            console.log(ville_arr);
          }
        }
      });
    })
    .catch(err => {
      // Performing actions
    });
});

To store the results as arrays within another array, my first approach is to push them like so:

ville_arr.push([el.nom, el.codesPostaux[0]])

The problem arises when duplicate items are added to the array due to repetitive API calls fetching the same results. To avoid this issue, I implemented the following check:

if(!ville_arr.includes([el.nom, el.codesPostaux[0]])){

    ville_arr.push([el.nom, el.codesPostaux[0]])
    console.log(ville_arr)

      }

Despite these adjustments, duplicates still persist in the final array. Could it be related to the unique indexes or something else entirely?

https://i.sstatic.net/TxUtm.png

Answer №1

Array.prototype.includes performs a referential equality check for objects.

This implies that even if you are adding objects with the same structure, they are not considered identical references as each addition creates a new object.

A common approach is to retain a unique identifier of an object instead, like an id.

Perhaps considering storing and checking for the zipcode could be beneficial?

if (!zipcodes.includes(el.codesPostaux[0])) {
  zipcodes.push(el.codesPostaux[0]);
  ville_arr.push([el.nom, el.codesPostaux[0]]);
}

An efficient method is utilizing a set of zipcodes rather than an array (due to the O(1) lookup time):

if (!zipcodesSet.has(el.codesPostaux[0])) {
  zipcodesSet.add(el.codesPostaux[0]);
  ville_arr.push([el.nom, el.codesPostaux[0]]);
}

If opting to solely use ville_arr, achieving the same outcome can also be accomplished using Array.prototype.every (or Array.prototype.some):

// this will return true if every location in ville_arr
// doesn't have the received zipcode
if (ville_arr.every(([, zipcode]) => zipcode !== el.codesPostaux[0])) {
  ville_arr.push([el.nom, el.codesPostaux[0]]);
}

Another option could involve applying JSON.stringify to your object to generate a consistent string representation of a specific object. This approach could work since includes conducts an equality comparison for primitive values such as strings.

Answer №2

Check out this solution:

const city_input = document.getElementById('search_real_estate_city');
let city_array = [];
city_input.addEventListener('keyup', () => {
    result_list.innerHTML = '';

    fetch(`https://api.fr/communes?nom=${city_input.value}`)
        .then(res => {

            // Clear old data when receiving new response
            city_array = [];

            return res.json();
        })
        .then(...)
        .catch(...);
});

You can also try using Array.prototype.find() (and additional information about find vs some on jsPerf.com):

if(!city_array.find(i => i[1] === el.postalCodes[0])) {

    city_array.push([el.name, el.postalCodes[0]]);
    console.log(city_array);
}

Answer №3

Array#includes does not check reference types based on their values; it verifies if their references are identical.

For instance, running this code will result in false:

var myArr = [[5, 6], [1, 2], [4, 5]];

console.log(myArr.includes([1, 2])); // false

This is because the array [1, 2] declared in line 1 is a different entity from the one in line 3, despite having the same values.

To address this issue, you can utilize Array#some, which takes a lambda function as input:

var myArr = [[5, 6], [1, 2], [4, 5]];

console.log(myArr.some(e => e[0] === 1 && e[1] === 2)); // true

Or applying this concept to your specific scenario:

if(!ville_arr.some(e => e[0] === el.nom && e[1] === el.codesPostaux[0])) {
    ville_arr.push([el.nom,el.codesPostaux[0]])
    console.log(ville_arr)
}

Answer №4

One unconventional method of achieving the same result is by creating an object (o) and populating it with sub-arrays using unique keys derived from the contents of each array. This approach allows the object to maintain its distinct structure independently:

var o={data:{},insert:function(name,code){this.data[name+code]=[name,code]},
get:function(){return Object.values(this.data)}};

To add values, you would use:

o.insert(element.name, element.postCode[0]);

To access the unique arrays stored in the object, you can utilize:

o.get()

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

Is it possible to trigger an ng-click event while the md-backdrop is present in Angular Material?

In my Angular Material website, a context menu pops up with an md-backdrop whenever the md-menu is shown. Clicking outside the md-menu closes it by triggering the md-backdrop click event. However, I would like to capture that ng-click event. For instance, ...

Displaying an image on canvas while showing a loading progress bar

I'm attempting to utilize this function to load an image into my canvas: function handleImage(e) { var reader = new FileReader(); reader.onload = function (event) { var img = new Image(); // img.onprogress = function (e) { ...

Error code 400 encountered when processing Stripe webhooks

I've been working on integrating stripe webhooks into my node.js/express application, but I keep running into a 400 response from the stripe cli. Even though I followed the documentation closely and ensured that the secret key for the webhook is corre ...

No response being received from Ajax request

Having some trouble with an ajax function I developed for a small project. The issue lies in running the code inside the .done() function. This function is supposed to receive a json object from php (which I am obtaining a response via cURL), but it appear ...

Converting Python code into JavaScript for use on an iPhone device

Having a web application with backend developed in Python (using Django) and front end in HTML5 & JavaScript, where Python generated data is transferred to JavaScript/HTML through JSON. Now, I want to transform it into a mobile application, starting with ...

Extensions fail to load on subsequent attempts in Forge Viewer

I am currently utilizing Reactjs to develop the Forge Viewer. After displaying the drawing in the Forge Viewer, I encountered an issue where extensions fail to load after the second time. List of extensions that were not loaded: Autodesk.ViewCubeUi. Aut ...

PHP encountered an error decrypting the JSON data it received from JavaScript

After sending a JSON string from JavaScript and receiving it in PHP, I noticed that my PHP script is not interpreting it as JSON. The JavaScript code generates the following output: {"id_own":"Metztli Alonso","tick":"123456","ticket":"TID","comm":"test v ...

How do the JavaScript thread and the Silverlight UI thread interact with each other?

While JavaScript operates on a single thread, Silverlight does not follow the same restrictions. However, when it comes to the interaction between JavaScript and Silverlight, it is crucial that communication occurs on the Silverlight UI thread. The relati ...

When attempting to display a basic mesh in Three.js, the render does not showcase a simple cube as expected

My objective is to display a simple plane and a cube, however, the cube is being hidden by the plane. The position of the cube is between the camera and the plane, but for some reason, the plane appears to be blocking the view of the cube. This is how my ...

Encountering a problem with npm reading dependencies

I decided to kickstart a new Node application by following a tutorial and creating a package.json file. Below is the content of my json file: { "name": "Dashboard", "version": "0.0.0", "description": "Client-A Dashboard", "dependencies": { ...

Show button once modal has been closed

I have a 'start' button that triggers a modal window with an embedded video. Once the user closes the modal, I want to show a 'redeem' button after a delay of 6 seconds. HTML: <a id="video-start" onclick="openVideoModal()"><i ...

I desire to exclude the final attribute of the object and instead assign its value to the preceding property

I am dealing with an object structure like the one below: let a = { title: { value:"developer" } publishedOn:{ month:{ value:"jan" } year:{ value:"2000" } } and I need to transform it into the followin ...

What causes an error when jqXHR.abort() is invoked in the beforeSend function?

Attempting to interrupt ajax call with beforeSend in case of a specific condition. Upon executing jqXHR.abort() or return false, I encounter the following error message: TypeError: $.ajax(...).fail is not a function .fail(function (jqXHR, textStatus, er ...

Retrieve latitude and longitude values from a string of varying length

Is there a way to extract latitude and longitude values from a string that contains multiple pairs, such as the following: var data = "(-20.210696507479017, -70.14000177383423),(-20.21202551027535, -70.14246940612793),(-20.21385790460967, -70.140666961669 ...

Steps to Turn Off Automatic Loading in Jquery Ajax tabs

I've encountered an issue with auto-loading in jQuery Ajax tabs. It's causing my browser to hang up. I need to find a way to disable the auto-loading feature. Here's the scenario of what I need: On the first tab, it loads the following cate ...

Storing a photo taken with a camera to a local directory on the computer

Currently, I am utilizing HTML5 inputs to capture a picture from the camera by using the code below: <input id="cameraInput" type="file" accept="image/*;capture=camera"></input> Subsequently, I am obtaining the image in blob format and manip ...

Challenges in displaying a preview of the cart following a successful ajax request

I'm trying to display a cart preview when hovering over a specific shopbag div. To achieve this, I've created another div called livebag where I run a query to fetch and preview the cart items stored in the database. Initially, the livebag div is ...

Exploring the process of updating initialState within react-redux

I am currently using react-redux to retrieve data from a MongoDB database and integrate it into my React App. Below is the structure I am working with: const initialState = { Level: [{ wId: Math.random(), Level1: [ { id: Math.rando ...

Obtain the result of two "Synchronous" nested queries using Express and Mongoose

I need to fetch an array of elements structured like this: ApiResponse = [ {_id: 1, name: Mike, transactions: 5}, {_id: 2, name: Jhon, Transactions: 10} ] The user data is retrieved from a query on the "Users" schema, while the tr ...

Tips for choosing or unselecting a row within a Table utilizing the Data Grid Mui

Is it possible to implement row selection and deselection in Mui without using the checkboxSelection prop? I am looking for a way to achieve this functionality in @mui/x-data-grid when clicking on a row. Below is the code snippet from the Table Component ...