How can you combine arrays in Javascript that are multidimensional?

Thank you for providing your responses. I appreciate the correct answers you shared based on the question. The error in the question was a result of my oversight, as I failed to include collecting the amount paid when combining user names. I am in the process of restructuring the code for accuracy.

const array =[
{
  name: 'Iphone',
  date: '01.01.2024',
  img: 'img/iphone.png',
  cost: 2500,
  paid: 500,
  username:"Joe",
},
{
  name: 'Samsung',
  date: '01.01.2024',
  img: 'img/samsung.png',
  cost: 2000,
  paid: 200,
  username:"Adam",
},
{
  name: 'Samsung',
  date: '01.01.2024',
  img: 'img/samsung.png',
  cost: 2000,
  paid: 100,
  username:"Alvin",
}
]

The data retrieved from my database requires a new arrangement to be combined effectively. Specifically, the sum of values in the Paid field needs to be calculated accordingly.

const array =[
{
 name: 'Iphone',
 date: '01.01.2024',
 img: 'img/iphone.png',
 cost: 2500,
 paid: 500,
 username:"Joe",
},
{
 name: 'Samsung',
 date: '01.01.2024',
 img: 'img/samsung.png',
 cost: 2000,
 paid: 300,   <---  accumulated paid amount from 2 Samsung entries
 usernames:[
   {username : "Adam"},
   {username : "Alvin"}
   ]
 }
]

Answer №1

const products = [
    {
        name: 'Iphone',
        date: '01.01.2024',
        img: 'img/iphone.png',
        cost: 2500,
        username: 'Joe',
    },
    {
        name: 'Samsung',
        date: '01.01.2024',
        img: 'img/samsung.png',
        cost: 2000,
        username: 'Adam',
    },
    {
        name: 'Samsung',
        date: '01.01.2024',
        img: 'img/samsung.png',
        cost: 2000,
        username: 'Alvin',
    },
];

const updatedProducts = products.reduce((acc, current) => {
    const foundProduct = acc.find(
        (existingProduct) =>
            existingProduct.name === current.name &&
            existingProduct.date === current.date &&
            existingProduct.img === current.img &&
            existingProduct.cost === current.cost
    );

    if (foundProduct) {
        foundProduct.usernames.push({ username: current.username });
    } else {
        acc.push({
            name: current.name,
            date: current.date,
            img: current.img,
            cost: current.cost,
            usernames: [{ username: current.username }],
        });
    }

    return acc;
}, []);

This snippet uses the reduce method to iterate over an array of products and transform them into a new array with unique entries based on specific criteria. If a product with matching attributes already exists in the accumulator, it adds the username to its list of usernames. Otherwise, it creates a new object with the username as the initial entry in the usernames array.

Answer №2

To improve performance, create a tree structure of property values with unique objects by all fields except the `username` field. This code is flexible and supports any number of properties. It can be encapsulated in a function where the array property name is passed as a parameter.

const result = array.reduce(((cached, keys, lastKey) => (r, item) => {
  if(!keys){
    keys = Object.keys(item).filter(key => key !== 'username');
    lastKey = keys.pop();
  }
  let node = cached;
  for(const key of keys){
    node = node[item[key]] ??= {};
  }
  const found = node[item[lastKey]];
  if(!found){
     r[r.length] = node[item[lastKey]] = {...item};
  }else{
    if(found.usernames){
      found.usernames.push({username: item.username});
    }else{
      found.usernames = [{username: found.username}, {username: item.username}];
      delete found.username;
    }
  }
  return r;
})({}), []);

console.log(result);
<script>
const array=[{name:"Iphone",date:"01.01.2024",img:"img/iphone.png",cost:2500,username:"Joe"},{name:"Samsung",date:"01.01.2024",img:"img/samsung.png",cost:2e3,username:"Adam"},{name:"Samsung",date:"01.01.2024",img:"img/samsung.png",cost:2e3,username:"Alvin"}];
</script>

` Chrome/120
-------------------------------------------------------
Alexander   1.00x  |  x1000000  660  680  683  719  745
Carsten     1.19x  |  x1000000  783  828  836  842  846
-------------------------------------------------------
https://github.com/silentmantra/benchmark `

// @benchmark Carsten     

Object.values(array.reduce((a,c)=>{
 const k=c.name+c.date+c.img+c.cost;
 if (!a[k]){ a[k]={...c, usernames:[]}; delete a[k].username;}
 a[k].usernames.push(c.username);
 return a;
},{}));


// @benchmark Alexander

array.reduce(((cached, keys, lastKey) => (r, item) => {
  if(!keys){
    keys = Object.keys(item).filter(key => key !== 'username');
    lastKey = keys.pop();
  }
  let node = cached;
  for(const key of keys){
    node = node[item[key]] ??= {};
  }
  const found = node[item[lastKey]];
  if(!found){
     r[r.length] = node[item[lastKey]] = {...item};
  }else{
    if(found.usernames){
      found.usernames.push({username: item.username});
    }else{
      found.usernames = [{username: found.username}, {username: item.username}];
      delete found.username;
    }
  }
  return r;
})({}), []);

/*@end*/eval(atob('e2xldCBlPWRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3Rvcigic2NyaXB0Iik7aWYoIWUubWF0Y2hlcygiW2JlbmNobWFya10iKSl7bGV0IHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7dC5zcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9naC9zaWxlbnRtYW50cmEvYmVuY2htYXJrL2xvYWRlci5qcyIsdC5kZWZlcj0hMCxkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHQpfX0='));
<script>
const array=[{name:"Iphone",date:"01.01.2024",img:"img/iphone.png",cost:2500,username:"Joe"},{name:"Samsung",date:"01.01.2024",img:"img/samsung.png",cost:2e3,username:"Adam"},{name:"Samsung",date:"01.01.2024",img:"img/samsung.png",cost:2e3,username:"Alvin"}];
</script>

Answer №3

Begin by obtaining the distinct phone models.

Next, loop through each model and locate the corresponding phone data, extracting all attributes into a new object. Then, include all user names associated with that particular phone model.

To finalize, if there are multiple user names, remove the individual username property from each object in the resulting array, leaving only a usernames property at the top level. If there is just one username, keep it and eliminate the usernames property.

const array = [{"name":"Iphone","date":"01.01.2024","img":"img/iphone.png","cost":2500,"username":"Joe"},{"name":"Samsung","date":"01.01.2024","img":"img/samsung.png","cost":2000,"username":"Adam"},{"name":"Samsung","date":"01.01.2024","img":"img/samsung.png","cost":2000,"username":"Alvin"}]

let names = [...new Set(array.map(i=>i.name))]

let array2 = names.map(name => ({
  ...array.find(i => i.name===name),
  usernames: array.filter(i => i.name===name)
                  .map(({username}) => ({username}))
}))

array2.forEach(i => {
  if(i.usernames.length > 1) delete i.username
  else delete i.usernames
})

console.log(array2)

Answer №4

A suggestion is to utilize a basic array structure for storing usernames. Here is a potential solution incorporating this approach:

const arr =[
{
  name: 'Apple',
  date: '01.01.2024',
  img: 'img/apple.png',
  cost: 2500,
  paid: 500,
  username:"John",
},
{
  name: 'Samsung',
  date: '01.01.2024',
  img: 'img/samsung.png',
  cost: 2000,
  paid: 200,
  username:"Alice",
},
{
  name: 'LG',
  date: '01.01.2024',
  img: 'img/lg.png',
  cost: 1800,
  paid: 100,
  username:"Ethan",
}];

const res=Object.values(arr.reduce((a,c)=>{
 const k=c.name+c.date+c.img+c.cost;
 if (!a[k]){ a[k]={...c, userlist:[]}; delete a[k].username;}
 else a[k].paid+=c.paid; 
 a[k].userlist.push(c.username);
 return a;
},{}));

console.log(res);

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

`The server fails to retrieve parameters passed through an angularJS HTTP GET request,

In my controller.js file, I've come across the following block of code: $http({ method: 'GET', url: '/getGuestList', params: {exhibitorID: 1} }) The purpose of this code is to fetch all the guests belonging to a parti ...

Provide Jquery with a named function for success plus some extra perplexity

Can anyone help me figure out why my JQUERY .ajax request won't accept a non-anonymous function in the success condition? I prefer not to use anonymous functions because I find them harder to debug and read. I've also heard that breaking out fun ...

How can I show the table row as an inner table row when the first field is identical?

<tr ng-model="check" ng-repeat="orderBook in orderBookDetails| orderBy: 'orderBook.no'" value='check=$scope.orderBookDetails.sowNo'> <td ng-if='check!=orderBook.no'>{{orderBook.no}}</td> <td>{{order ...

Tips for ensuring that the first div of a collapsible div remains expanded whenever a dropdown is changed in AngularJS

There are collapsed and expanded div elements, with the first div always open on load. I want to ensure that the first div remains open even when changing the dropdown selection. The current implementation works partially, as expanding any div and then c ...

How can I incorporate Bootstrap multi-select into the jQuery DataTables DOM?

Having trouble implementing a bootstrap multi-select inside a jQuery datatable DOM. I followed this example to add a custom element within the jQuery datatable container. It works fine for normal bootstrap select, but when trying to add a bootstrap multi-s ...

Encountering a CORS header issue while working with the Authorization header

Here is the code snippet I am currently working with: https://i.stack.imgur.com/DYnny.png Removing the Authorization header from the headers results in a successful request and response. However, including the Authorization header leads to an error. http ...

The function url_for is failing to interpret the variables I am passing to

My goal is to allow users to upload images that are then displayed to all users. The variable "Data" holds the file name (e.g., "files/dog.png"). However, when I try to set the newImg.src value as "{{url_for('static', filename = data )}}", it onl ...

Identifying the absence of a character at the end of the last line in Node.js to detect

Currently, I am processing data line by line from a buffer. Within the buffer, the data is structured as follows: name,email,phn test1,<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="47332234337607223f262a372b226924282a">[em ...

In JavaScript, the function is unable to access elements within an iteration of ng-repeat

I am using ng-repeat to display datepickers that are powered by flatpickr. To make this work, a script needs to be added on the page for each input element like so: <script> $('[name="DOB"]').flatpickr({ enableTime: false, dateForm ...

Issue with Dijit form fields failing to render correctly following dojo.destroy and dojo.place operations

Within my form, there is a table labeled as table0 which contains various dijit form controls. Additionally, there are buttons for adding and removing tables where each new table is assigned an ID incremented by 1. For instance, the first click on the add ...

Alter elements in HTML dynamically based on the value of a cookie

I am trying to dynamically change HTML links on my website based on a cookie variable that is set by PHP. The cookie value is updated every minute through a periodic request. To ensure that the JavaScript variable remains up-to-date, I want to check it e ...

What is the most efficient way to create a bufferGeometry with multiple particle sizes for optimal performance?

Using a bufferGeometry, I created a THREE.Point object to display thousands of particles with the PointsMaterial material. Changing textures and colors on runtime worked perfectly for me. However, I faced an issue when trying to have particles of differen ...

Perform the Checkbox action when it is marked

How to trigger href from input checkbox when it is checked Example of Checkbox Input Code: <input type="checkbox" value="{{$todo -> id}}" name="{{$todo -> ToDoName}}"> JavaScript Code: /* Custom todo list plugin */ $(".todo-list").todolis ...

Is there a method to verify if a GeoJSON feature is in the shape of a rectangle and locate its corner coordinates?

I am looking for a way to identify all the corner coordinates of GeoJSON features that are in rectangular or square shape. Some of the features have more than five coordinates but still represent a rectangle or square shape. Is there an algorithm or third- ...

Jest: A guide on mocking esModule methods

In my code, I have a function that utilizes the library jszip to zip folders and files: // app.ts const runJszip = async (): Promise<void> => { const zip = new Jszip(); zip.folder('folder')?.file('file.txt', 'just som ...

Controlling the Quantity of Selected Checkboxes with JavaScript

I am facing an issue with implementing multiple checkboxes with limits in JavaScript, as shown below. $(".checkbox-limit").on('change', function(evt) { var limit = parseInt($(this).parent().data("limit")); if($(this).siblings(':checked&ap ...

Tips for creating an effective dark mode toggle switch on a website

I was experimenting with creating a dark-mode switch for a website, but I'm not convinced that my implementation is the most efficient. Essentially, I ended up duplicating each file and adding a "2" at the end to create modified versions for each sect ...

Adding data to a JavaScript array with two dimensions

Having some trouble adding values to an array in JavaScript. I'm still new to this language. Below is the code: eventsArray = new Array(); $.each(xmlJsonObj.feed.entry, function(index, value){ eventsArray[index] = new Array('title' = ...

using javascript to create two choices

I am facing a small complication between two select options in my javascript code. Here is the snippet of my javascript: function displayVals() { var singleValues = $("select option:selected").text(); //to stay selected $("#hiddenselect").val(s ...

Are there any PHP methods available for imploding an associative array while retaining the keys intact?

Explaining the title of this query is unnecessary. I've been told that I can achieve this by using http_build_query, but I prefer a specific function for this purpose. Here is an example of the input: $assoc = array( "fruit" => "banana", ...