Consolidate array elements based on their respective categories

I am stuck with this array:

[ [ 'TWENTY', 20 ],
  [ 'TWENTY', 20 ],
  [ 'TWENTY', 20 ],
  [ 'TEN', 10 ],
  [ 'TEN', 10 ],
  [ 'FIVE', 5 ],
  [ 'FIVE', 5 ],
  [ 'FIVE', 5 ],
  [ 'DOLLAR', 1 ],
  [ 'QUARTER', 0.25 ],
  [ 'QUARTER', 0.25 ],
  [ 'DIME', 0.1 ],
  [ 'DIME', 0.1 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ] ]

My goal is to combine the values so that I end up with:

[ [ 'TWENTY', 60 ],
  [ 'TEN', 20 ],
  [ 'FIVE', 15 ],
  [ 'DOLLAR', 1 ],
  [ 'QUARTER', 0.50 ],
  [ 'DIME', 0.2 ],
  [ 'PENNY', 0.04 ]]

I attempted to go through each element in the array and add up the values, but unfortunately, it didn't work out as expected. I would greatly appreciate any assistance. Mattia P

Answer №1

Here is a clever approach to achieving this task using just one loop and an object acting as a map:

const values = [ [ 'TWENTY', 20 ],
  [ 'TWENTY', 20 ],
  [ 'TEN', 10 ],
  [ 'TEN', 10 ],
  [ 'FIVE', 5 ],
  [ 'DOLLAR', 1 ],
  [ 'QUARTER', 0.25 ],
  [ 'DIME', 0.1 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ] ];
  
const output = values.reduce((map,[key,val]) => {
  map[key] = (map[key] || 0) + val;
  return map;
}, {});

console.log(Object.entries(output));

The Object.entries(output) method converts the result back into an array format for easier access if needed, allowing you to optimize your use of the map structure.

Answer №2

By utilizing the .reduce() and .find(), you have the ability to group elements based on the first item in each inner array.

Give this a try:

const array = [ [ 'TWENTY', 20 ],
  [ 'TWENTY', 20 ],
  [ 'TWENTY', 20 ],
  [ 'TEN', 10 ],
  [ 'TEN', 10 ],
  [ 'FIVE', 5 ],
  [ 'FIVE', 5 ],
  [ 'FIVE', 5 ],
  [ 'DOLLAR', 1 ],
  [ 'QUARTER', 0.25 ],
  [ 'QUARTER', 0.25 ],
  [ 'DIME', 0.1 ],
  [ 'DIME', 0.1 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ],
  [ 'PENNY', 0.01 ] ];
  
const result = array.reduce((a, c) => {
  const found = a.find(f => f[0] === c[0]);
  
  if (found) found[1] += c[1];
  else a.push(c);

  return a;
}, []);

console.log(result);

I trust this solution will be of assistance to you!

Answer №3

If you want a concise solution, consider using a Map.

var data = [['TWENTY', 20], ['TWENTY', 20], ['TWENTY', 20], ['TEN', 10], ['TEN', 10], ['FIVE', 5], ['FIVE', 5], ['FIVE', 5], ['DOLLAR', 1], ['QUARTER', 0.25], ['QUARTER', 0.25], ['DIME', 0.1], ['DIME', 0.1], ['PENNY', 0.01], ['PENNY', 0.01], ['PENNY', 0.01], ['PENNY', 0.01]],
    result = Array.from(data.reduce((m, [k, v]) => m.set(k, (m.get(k) || 0) + v), new Map));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №4

let moneyValues = [['TWENTY', 20],
 ['TWENTY', 20],
 ['TWENTY', 20],
 ['TEN', 10],
 ['TEN', 10],
 ['FIVE', 5],
 ['FIVE', 5],
 ['FIVE', 5],
 ['DOLLAR', 1],
 ['QUARTER', 0.25],
 ['QUARTER', 0.25],
 ['DIME', 0.1],
 ['DIME', 0.1],
 ['PENNY', 0.01],
 ['PENNY', 0.01],
 ['PENNY', 0.01],
 ['PENNY', 0.01]];

 let totalMoney = {};
 let finalCount = [];

 for (const [name, value] of moneyValues) {
  if (!totalMoney[name]) {
    totalMoney[name] = 0;
  }
  totalMoney[name] += value
 }
 for (const [key, value] of Object.entries(totalMoney)) {
  finalCount.push([key, value])
 }

console.log(finalCount)

Answer №5

To achieve this, you can utilize both the reduce and findIndex methods.

const myData = [[ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TEN', 10 ], [ 'TEN', 10 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'DOLLAR', 1 ], [ 'QUARTER', 0.25 ], [ 'QUARTER', 0.25 ], [ 'DIME', 0.1 ], [ 'DIME', 0.1 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ]];

const result = myData.reduce((accumulator, [key, value]) => {
  let indexFound = accumulator.findIndex(item => item[0] === key);

  if (indexFound === -1) {
    accumulator.push([key, value]);
  } else {
    accumulator[indexFound][1] += value;
  }
  return accumulator;
}, []);

console.log(result);
.as-console-wrapper {
  min-height: 100% !important;
  top: 0;
}

Answer №6

This code snippet showcases a clever solution that requires only one iteration:

const transaction = [
    ['TWENTY', 20],
    ['TWENTY', 20],
    ['TWENTY', 20],
    ['TEN', 10],
    ['TEN', 10],
    ['FIVE', 5],
    ['FIVE', 5],
    ['FIVE', 5],
    ['DOLLAR', 1],
    ['QUARTER', 0.25],
    ['QUARTER', 0.25],
    ['DIME', 0.1],
    ['DIME', 0.1],
    ['PENNY', 0.01],
    ['PENNY', 0.01],
    ['PENNY', 0.01],
    ['PENNY', 0.01]
];

let totalAmount = {};
transaction.forEach(item => {
      if(totalAmount[item[0]]) {
         totalAmount[item[0]][1] += item[1];
      } else {
         totalAmount[item[0]] = item;   
      }
});
console.log(totalAmount);

Answer №7

To simplify this into a basic function, it could be written as shown below:

const calculateTotal = arr => Object .entries (arr .reduce (
  (acc, [name, val]) => ({...acc, [name]: (acc [name] || 0) + val})
  , {}
))

const coinsArray = [ [ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TWENTY', 20 ], [ 'TEN', 10 ], [ 'TEN', 10 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'FIVE', 5 ], [ 'DOLLAR', 1 ], [ 'QUARTER', 0.25 ], [ 'QUARTER', 0.25 ], [ 'DIME', 0.1 ], [ 'DIME', 0.1 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ], [ 'PENNY', 0.01 ] ];

console .log (calculateTotal (coinsArray))
.as-console-wrapper {min-height: 100% !important; top: 0}

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

Checking Sudoku Solutions on Codewars

I have come across this JavaScript code which seems to be functioning correctly. However, I am curious about the line board[3][8] != board[8][3] and how it checks for repeating row and column numbers. Can someone please provide an explanation? Thank you! ...

Align pictures in the middle of two divisions within a segment

This is the current code: HTML: <section class="sponsorSection"> <div class="sponsorImageRow"> <div class="sponsorImageColumn"> <img src="img/kvadrat_logo.png" class="sponsorpicture1"/> </div& ...

What is the best way to switch out the characters 'a' and 'b' in a given string?

Let's say we have the following text. Lorem ipsum dolor sit amet The revised text should look like this: merol merol merol merol Is there a predefined function in JavaScript that can help us replace characters like this within a string? ...

Combining JSON arrays into a single multidimensional array

I have received the following JSON data from an API, and unfortunately, I do not have control over its format. Hence, changing the format is not feasible for me. I am facing difficulty in combining this JSON data into a single JSON array. My goal is to pr ...

Dropdown selection not getting updated when modifying DropdownSection component

My Link dropdown triggers a DropdownSection component that includes an array of options. If I switch to a different Link, I want the default option in the DropdownSection to be set to the second option from the linkOptions array, skipping the initial "No ...

Looking to scan through a directory of .html files in Node.js to find specific element attributes?

Imagine trying to tackle this task - it's like reaching for a needle in a haystack. Picture a folder containing a static website, complete with images, stylesheets, and HTML files. My Node application needs to dive into this folder and extract only th ...

Issue with calling hooks. Hooks can only be invoked within the body of a function component

Looking to develop a todo application using React, but encountering an issue with the useContext hook. The error message "Invalid hook call..." suggests a few possible reasons for this problem: Possible mismatched versions of React and the renderer (e.g ...

Combining Various Input Types for Seamless Integration: Getting Files and Text to Collaborate Efficiently

In my form, I have two types of image inputs - one from a file and the other from a URL. To ensure that the image from the last changed input is used, I created an additional invisible input field called "imgTempURL". This field is filled with the image&ap ...

Middleware in Express.js Router

In the following code snippet, I am aiming to limit access to the 'restrictedRoutes' routes without proper authorization. However, I am encountering an issue where 'restrictedRoutes' is affecting all routes except for those within the & ...

In react-native, both the parent and child components are rendered at the same time

One of my components, the parent one, goes through an array of chapters and for each item found, renders a child component called 'ExercisesList' and passes an array of exercises to it. class ExercisesScreen extends Component { displaySelected ...

What techniques can be utilized to obscure Tailwindcss HTML class names when deploying to production?

Is there a way to camouflage the HTML classnames in production while utilizing Tailwindcss? My current setup involves React.js and CRACO, following the guidelines provided in Tailwind's documentation. ...

Maintaining scope integrity in an Angular application with components, including a dialog that utilizes a custom directive

I'm struggling with passing scope to a template rendered from a directive. It seems like it should be simple, but I can't seem to get it to work properly. Here is a simplified version of my HTML: <div ng-app="myApp"> <md-content> ...

Changing the counter using dual buttons in Vue.js

I am facing an issue with updating the counter when using both the add and remove buttons. The add button functions correctly, but unfortunately, the delete button does not update the counter as expected. Below is a picture showcasing the problem at hand: ...

Receiving data through multiple ajax calls nested within another ajax call

Hello everyone, I am diving into the world of AJAX/jQuery and would appreciate your patience as I try to navigate through it. I have an interesting challenge ahead so let's see how we can tackle it together ...

What is the method for turning off client-side validation for a specific field with jQuery when a checkbox is selected?

This is the HTML code used in my MVC Razor page. <form> <input id="inputLPR" asp-for="LicensePlateNo" class="form-control"/> <input type="checkbox" id="isEnableBypass"><label for=&qu ...

Try fetching new data with React Query by refetching

Whenever a button is clicked, I attempt to fetch new data by calling Refetch. const {refetch,data,isLoading} = useQuery( "getkurs",() =>fetch( `https://free.currconv.com/api/v7/convert? q=${selected.country.currencyId}_IDR&compa ...

<fieldset> triggering onChange event in React form

I am facing an issue with my React component where multiple onChange functions are not getting fired. After some debugging, I realized that the problem lies with the fieldset element within the form. Removing the fieldset allows all onChange functions to w ...

Update the text for the filter search placeholder in the Ant Table component

Is there a way to alter the default placeholder text in the Ant Table? I've set up a functioning example in documentation but couldn't find any prop for customization besides the customized filter dropdown, which I didn't want to implement. ...

The function 'find' cannot be invoked on an undefined object

I'm currently working on implementing objects in my jQuery code. So far, I have the following: var options = { ul: $(this).find('.carousel'), li: options.ul.find('li') } The li property is causing an error - Cannot call meth ...

Using vue-select: In VueJs, how to pass an option slot from a grandparent component

Utilizing a custom dropdown component called 'vue-select', there is an option to customize the options view using slots as detailed in this documentation -> https://vue-select.org/guide/slots.html I am aiming to achieve a similar customizatio ...