What is the best way to combine identical items in a JavaScript array?

I AM LOOKING TO COMBINE DUPLICATED ITEMS AND THEN DELETE THEM

here is the sample array for testing:

var arr = [{
    'id': 1,
    'text': 'ab'
}, {
    'id': 1,
    'text': 'cd'
}, {
    'id': 2,
    'text': 'other'
}, {
    'id': 3,
    'text': 'afafas'
}, {
    'id': 1,
    'text': 'test'
}, {
    'id': 4,
    'text': 'asfasfa'
}];

the expected result should be:

[{
    'id': 1,
    'text': "[ab] [cd] [test]"
}, {
    'id': 2,
    'text': 'other'
}, {
    'id': 3,
    'text': 'afafas'
}, {
    'id': 4,
    'text': 'asfasfa'
}]

the flow of operation goes like this > if there are items with duplicate IDs, the text field of those items should be merged into one and duplicates must be removed to keep unique values based on the text field. For example, text: "[text1] [text2] [text3] [text4]" You can refer to my previous question Merge duplicated items in array but the existing answers only handle scenarios with 2 duplicates.

I have tried the following code, however it only handles cases with 2 duplicates and fails when there are 3 or more duplicates:

arr.forEach(function(item, idx){   

   //Now lets go through it from the next element
   for (var i = idx + 1; i < arr.length; i++) {

     //Check if the id matches
     if (item.id === arr[i].id) {

        //If the text field is already an array just add the element        
        if (arr[idx].text.constructor === Array) {
            arr[idx].text.push('[' + arr[i].text + ']');   
         }
         else {  //Create an array if not
            arr[idx].text = new Array('[' + arr[idx].text + ']', '[' + arr[i].text + ']');
         }

		    //Delete this duplicate item
         arr.splice(i, 1);
      }      
   }

 });

Answer №1

Both methods utilize a temporary object to reference the item by its id.

The first method, known as the in situ version, modifies the original array by removing duplicate items.

On the other hand, the alternative approach creates a new array and assigns the text property accordingly.

A variant of the in situ technique is demonstrated below:

var arr = [...],
    reference = {}, r,
    i = 0;

while (i < arr.length) {
    if (!reference[arr[i].id]) {
        reference[arr[i].id] = arr[i];
        i++;
        continue;
    }
    r = reference[arr[i].id];
    if (r.text[0] !== '[') {
        r.text = '[' + r.text + ']';
    }
    r.text += ' [' + arr[i].text + ']';
    arr.splice(i, 1);
}
document.write('<pre>' + JSON.stringify(arr, 0, 4) + '</pre>');

This particular solution generates a new array:

var arr = [...],
    result = arr.reduce(function (r, a) {
        if (!r.obj[a.id]) {
            r.obj[a.id] = { id: a.id, text: '' };
            r.array.push(r.obj[a.id]);
        }
        if (r.obj[a.id].text === '') {
            r.obj[a.id].text = a.text;
        } else {
            if (r.obj[a.id].text[0] !== '[') {
                r.obj[a.id].text = '[' + r.obj[a.id].text + ']';
            }
            r.obj[a.id].text += ' [' + a.text + ']';
        }

        return r;
    }, { array: [], obj: {} }).array;

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

Answer №2

Does this meet your requirements?

function mergeArrayElements(arr) {
    var newArr = [];

    arr.forEach(function(element) {
        var index;

        if (newArr.some(function(item, i) {
            index = i;
            return item.id === element.id;
        })) {
          if (!/\[|\]/.test(newArr[index].text)) {
            newArr[index].text = newArr[index].text.replace(/^(.*)$/g, "[$1]")
          }
            newArr[index].text += "[" + element.text + "]";
            newArr[index].text = newArr[index].text.replace(/\]\[/g, "] [");
        } else {
          newArr.push({
            id: element.id,
            text: element.text.replace(/^(.*)$/g, "[$1]")
          });
        }
    });

  newArr.forEach(function(a) {
    if (!/ /g.test(a.text)) {
       a.text = a.text.replace(/\[|\]/g, "");
    }
  });

  return newArr;
}

Answer №3

In this particular scenario, I have taken values and converted them into objects before converting them into arrays. If the identification can be in string format, it is advisable to utilize objects instead of arrays. This approach will prevent the need for additional loops to retrieve data.

var arr = [{
    'id': 1,
    'text': 'ab'
}, {
    'id': 1,
    'text': 'cd'
}, {
    'id': 2,
    'text': 'other'
}, {
    'id': 3,
    'text': 'afafas'
}, {
    'id': 1,
    'text': 'test'
}, {
    'id': 4,
    'text': 'asfasfa'
}];

var _temp = {};
var final = [];
arr.forEach(function(item){
  if(!_temp[item.id])
    _temp[item.id] = [];
  _temp[item.id].push(item.text);
});

Object.keys(_temp).forEach(function(k){
  var val = "";
  if(_temp[k].length>1){
    val = "[ " + _temp[k].join(" ] [ ") + " ]";
  }
  else
    val = _temp[k][0];
  
  final.push({
    id:k,
    text: val
  });
});

console.log("Object: ", _temp);
console.log("Array of Objects: ", final)

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

Spin the mergeometry object around its center in Three.js

I've been struggling to figure out how to rotate the object at its center. Right now, I can rotate the scene but the object moves away from the user. I've tried looking at similar questions on forums, but haven't been able to make it work. B ...

Display all dependents associated with a dependency in the lock file

Is there a way to identify all dependents of a specific dependency from a lock file (npm/pnpm/yarn)? This is the opposite of using yarn ls I would rather not parse the lock file if there is an existing command in npm/pnpm/yarn for this I am aware that I ...

Expecting function to return an undefined response object

My experience with async/await is limited, but I have used these keywords in a function that retrieves or posts data to a MongoDB database. However, it seems like the await keyword does not wait for the promise to be fulfilled and instead returns an undefi ...

Using both the jQuery attr and prop methods simultaneously in a script

In my jQuery script, I am trying to disable input fields with the following code: jQuery(".disabableInputField").addClass("disabledInputField"); cstaIpVal[0] = jQuery("#private-circuit-to-csta-subnet").val(); cstaIpVal[1] = jQuery( ...

Navigating router queries within Nuxt: A step-by-step guide

One of the challenges I am facing is passing value parameters in my URL with the mounted function looking like this: mounted () { this.$router.push({ path: '/activatewithphone', query: { serial: this.$route.params.serial, machin ...

What measures can be taken to safeguard my web app from unauthorized devices attempting to connect?

I am looking for a way to restrict access to a webapp so that only authorized users can connect from approved computers or mobile devices. If a user enters the correct username and password, access will be granted only if they are using a device approved b ...

What's the scoop on ng-animate and personalized directives?

How can I add custom animation to my custom directive successfully? .directive('home', function ($animate) { return { templateUrl: 'views/pantone-inner-home.html', restrict: 'AE', link: function postLink( ...

Accessing JavaScript elements from PHP code

Is it possible to recognize JavaScript elements if they are nested within PHP tags? For example: <?php $username = "maniacal"; echo "<p class='welcome' id='greeting'>Hi, Welcome to the site!!</p>" ?> That's ...

Is there a way to find the nth instance of a specific substring within a given string using Javascript?

My query involves a basic string "A <br> B <br/> C <br /> D <br>" combined with a range of potential substrings, such as ['<br>', '<br/>', '<br />']; It's straightforw ...

What is the best way to integrate Handlebars with Express?

Understanding the question isn't tough, but I'm unsure about integrating handlebars with Express. This is my current code: var express = require('express'); var app = express(); app.get('/', function (req, res, next) { ...

What is the best way to provide two unique versions of websites using one domain?

I've embarked on a project that requires a complete rewrite. Instead of opting for a big bang release, we've decided to utilize the Strangler Pattern as outlined here. The current application (details below) will continue to run unchanged under ...

Updating a Hidden Field in SharePoint with jQuery

When attempting to set the value of a site column (field) using jQuery, I encountered an issue where it only worked when the field was not hidden. The code I used was: $("select[Title='MyID']").val(MyRelatedID); Upon further inspection, it ...

Navigating the parent navController in Ionic 2: A step-by-step guide

I'm currently honing my skills in Ionic 2 by creating a basic app, but I've encountered an issue that has me stumped. The app features an ion-nav element for the login page, then transitions to a tabs navigator after successful login. The struct ...

Developing a dynamic, live updating ordering platform using Firebase

Recently, I stumbled upon Firebase and it seems like the perfect fit for my project. My goal is to create a real-time HTML dashboard for ordering, but as a beginner in JavaScript, I could really use some assistance. I envision a real-time dashboard that s ...

When the jQuery button is clicked, the execute function will run multiple times

I am attempting to create a button using jQuery that calls a JavaScript function, but I am facing an issue : Upon loading the page, the first click on mybutton does not elicit any response The second click results in the function being executed twice On ...

Issue with Laravel: unable to send data through ajax requests

I have developed a custom jQuery plugin specifically tailored for Laravel to facilitate sending data via Ajax to the server. However, I seem to be facing an issue where no data is being sent successfully. When I use dd($request->all()) to inspect what h ...

Using Javascript to place an image on top of another image (specifically for a close button)

I need help figuring out how to overlay a close icon image on top of another image using JavaScript. Specifically, I want to position the close icon in the top right corner of the image. Current code snippet: function drawImages(imagevalue){ var ar ...

Using React to Identify the Chosen Option on a Custom Toggle Button

I have successfully implemented a toggle switch using HTML and CSS in my React app. I am now looking for a way to detect the selected option whenever it changes. For instance, if OR is chosen, I would like it to be saved in the selectedOption state, and if ...

Discord.js reaction event handling

I'm in the process of developing a starboard feature for my bot, and everything is functioning well. However, I am facing an issue where I want the bot to ignore reactions made by the author of the original message. Here is the current code snippet: ...

Dynamically add new values or create interfaces in Typescript on the fly

I am working with an Angular Material Table and I have created an interface that serves as the dataSource for the table. However, I am facing a challenge because the data coming from the backend is unknown. Is there a way to dynamically add a new value to ...