Arranging numerical strings of an "advanced" nature in numerical sequence

Consider the following array:

var fees = [
    '$0.9 + $0.1',
    '$20 + $2',
    '$0.7 + $0.4',
    '$5 + $0.5',
    '$0 + $0.01',
    '$100 + $9',
    '$1 + $1',
    '$2 + $0.5'
];

If I wanted to sort these string values in numeric ascending order using vanilla JavaScript, how would I go about it?

The expected output after sorting should be:

function mySort(a, b) {
    return ((a < b) ? -1 : ((a > b) ? 1 : 0));
}

However, this only gives me:

"$0.9 + $0.1" and "$0.7 + $0.4", the sum favors the former, but I want to prioritize the latter. Essentially, I aim to sort based on the first number in ascending order, and if the first numbers match, then consider the second number for sorting.

Answer №1

Organize by the total sum of numbers within a string.

var fees = ['$0.9 + $.1', '$20 + $2', '$5 + $0.5', '$0 + $0.01', '$100 + $9', '$1 + $1', '$2 + $0.5'];

fees.sort(function(a, b) {
  return getSum(a) - getSum(b);
})

function getSum(str) {
  return str
    // remove the $ and space
    .replace(/[^\d+.]/g, '')
    //split by + symbol
    .split('+')
    // calculate the sum
    .reduce(function(sum, s) {
      // parse and add with sum
      return sum + (Number(s) || 0);
      // set initial value to sum
    }, 0)
}

console.log(fees);


You can optimize the process by utilizing an additional object that stores the sums.

var fees = ['$0.9 + $.1', '$20 + $2', '$5 + $0.5', '$0 + $0.01', '$100 + $9', '$1 + $1', '$2 + $0.5'];

var ref = fees.reduce(function(obj, str) {
  // define object property if not defined
  obj[str] = str in obj || str
    // remove the $ and space
    .replace(/[^\d+.]/g, '')
    //split by + symbol
    .split('+')
    // calculate the sum
    .reduce(function(sum, s) {
      // parse and add with sum
      return sum + (Number(s) || 0);
      // set initial value to sum
    }, 0);
  // return the object reference
  return obj;
  // set initial value as an empty object
}, {})

fees.sort(function(a, b) {
  return ref[a] - ref[b];
})

console.log(fees);


UPDATE: Since you had updated the question you need to compare the individual parts.

var fees = ['$0.9 + $.1', '$20 + $2', '$5 + $0.5', '$0 + $0.01', '$100 + $9', '$1 + $1', '$2 + $0.5'];

fees.sort(function(a, b) {
  // extract numbers from a
  var arrA = a.replace(/[^\d.+]/g, '').split('+');
  // extract numbers from b
  var arrB = b.replace(/[^\d.+]/g, '').split('+');

  // generate sort value
  return arrA[0] - arrB[0] || arrA[1] - arrB[1];
})

console.log(fees);

Answer №2

A three-step algorithm can be utilized for this sorting task:

  1. First, add the two values to be sorted by to each element
  2. Next, sort the elements based on those added values
  3. Finally, remove the extra information that was temporarily added

Below is the ES6 code snippet for achieving this:

var result = fees.map( s => [s].concat(s.match(/[\d.]+/g).map(Number)) )
                .sort( (a, b) => a[1] - b[1] || a[2] - b[2])
                .map( a => a[0] );

The s.match() function will generate an array with two matched strings. The subsequent map() operation will convert these strings into numerical values, and concat() will combine them with the original string to form a triplet.

The sorting comparison function will arrange the elements primarily by the first number (located at index 1), resorting to the second number if the first numbers are equal.

In the final map() call, only the original string from the triplets will be retained, discarding the additional sorting information.

The provided code sample includes an extra element in the input data ($5.1 + $0.1), showcasing the distinction between sorting by sums versus the desired sorting criteria outlined in the question.

By implementing this approach, the regular expression is applied just once per string, enhancing performance compared to integrating it within a sort callback where repeated comparisons may occur.

Answer №3

To organize the strings, you can extract their components, calculate the sum, and determine the difference between two elements for sorting purposes.

var charges = ['$0.9 + $.1', '$20 + $2', '$5 + $0.5', '$0 + $0.01', '$100 + $9', '$1 + $1', '$2 + $0.5'];

charges.sort(function (a, b) {
    function fetchValues(str) {
        return str.match(/([0-9.]+)/g).map(Number);
    }
    
    var firstCharge = fetchValues(a),
        secondCharge = fetchValues(b);
    return firstCharge[0] + firstCharge[1] - (secondCharge[0] + secondCharge[1]);
});

console.log(charges);

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

How can you use Angular to copy a value from one field to another through coding?

Seeking help with an Angular issue... I have a specific component that is being used in a template-driven form within my project. (Just for your reference, I am utilizing PrimeFaces UI components.) The scenario is as follows: When a user selects the "No" r ...

There appears to be a JavaScript validation error occurring on the current page, however, you are able

For my datepicker, I want an error message to display if the user selects a date more than 5 years in the future, saying "You are ineligible for our program". The user should not be able to proceed to the next step unless this error message is ad ...

"Successfully tested API request in Postman, however encountering issues when sending request in Node.js using the 'request

Currently, I am tackling a project that involves communicating with an API using nodeJS. It's quite a substantial project, so I'll provide you with a simplified version of my script. When I make a PUT request to the API using Postman, everything ...

How can I store an access token received from the backend (in JSON format) in local storage and use it to log in?

My goal is to create a login interface using Plain Javascript. I have obtained a Token from the backend and now need assistance in utilizing this Token for the login process and storing it in LocalStorage. Although I have successfully made the API call, I ...

Concealing the NavBar When Showing a Popup Using React

I am facing a challenge with hiding my bootstrap navbar that has a CSS property of position: sticky-top when I display a pop-up slideshow. I am working with React. I have attempted to target the navbar element in my click handler and adjust the display pro ...

Should Angular libraries be developed using Typescript or transpiled into JavaScript?

Currently, I am in the process of developing a library that will be available as an Angular module through npm. The library itself has been written using typescript. Everything was functioning perfectly up until Angular version 5.0.0, but after this update ...

Retrieve the weekday dates for a specific year, month, and relative week number using Javascript or Typescript

I am in need of a custom function called getDaysOfWeekDates that can take a year, a month (ranging from 0 to 11), and the week number of each month (usually 4-5 weeks per month) as parameters, and return a list of dates containing each day of that particul ...

Issue encountered: Failure in automating login through Cypress UI with Keycloak

Struggling with automating an e-commerce store front using Cypress, specifically encountering issues with the login functionality. The authentication and identity tool in use is keycloak. However, the Cypress test fails to successfully log in or register ...

Why isn't JQuery's .prependTo('body') function functioning correctly?

It's getting late and I should probably call it a night, but I am completely puzzled. I hate to admit it, but why isn't this working?? var informationBox = ''; informationBox += '<div class="informationBox">'; informati ...

I am looking for a way to save a webpage as .html/.png format after entering text in the text box. Here is the code I have

Is it possible to download a webpage as .html/.png after inputting text in the text box? Here is my code: <div class="container"> <form> <div class="form-group"> <label for="link">Paste Website Link Below</label> ...

"Is there a way to determine the height of an inline element, such as a span element,

var mySpan=document.getElementById("mySpan"); alert(mySpan.height); <span id="mySpan" style="line-height:200px;">hello world</span> However, the result I receive is undefined. This is because Javascript can only retrieve the he ...

How to create a calendar selection input using PHP?

Before I start writing the code myself, I am searching to see if there is already a solution available or if someone has previously outsourced the code. Below is an example of my date selection: https://i.sstatic.net/KqIDH.png I want to create a feature ...

Is it possible to track and listen for the download complete event while using an anchor tag to initiate the download process?

When using the anchor tag to automate downloads, is it possible to listen for events on the anchor tag? downloadMyFile(){ const link = document.createElement('a'); link.setAttribute('href', 'abc.net/files/test.ino'); ...

The bar graph dataset is not correctly configured when utilizing ng2 charts and ng5-slider within an Angular framework

Currently, I am working with a range slider and bar graph. My goal is to dynamically change the color of the bar graph using the range slider. While I have managed to successfully alter the color of the bars, I am facing an issue where the data displayed ...

Is it possible to utilize Math.Round within the <return> tag when coding in React?

Is there a way to calculate the value of a progress bar in the render part of React without using state? I want to know if this is possible. <div> <div id="myProgress"> <div id="myBar"> Math.ro ...

Combining React with Typescript allows for deep merging of nested defaultProps

As I work on a React and Typescript component, I find myself needing to set default props that include nested data objects. Below is a simplified version of the component in question: type Props = { someProp: string, user: { blocked: boole ...

Overcome the issue of 'Parsing Error: Kindly verify your selector. (line XX)' in Javascript/AWQL

Hello there! Just to clarify, I am not a developer and my coding skills are limited to basic HTML. Your patience is greatly appreciated ...

Drawing mysteriously disappeared from the canvas

Having trouble with my JavaScript code. I created a function called drawLine to trace lines on a canvas from one point (x,y) to another point (xdest, ydest). The first few lines display correctly but after the fourth line, it stops working and I can't ...

Expanding the canvas leads to the freezing of the Ionic app on the emulator

I'm currently working on developing an ionic app that includes the feature of allowing users to sign their name on a canvas. I am utilizing signature-pad.js from https://github.com/szimek/signature_pad to create this signature functionality. Everythi ...

Is there a way to extract SVG data from the Echarts library in AngularJS?

Currently, I am attempting to retrieve the SVG of Echarts elements in angularjs. Despite my efforts to search for a solution, I have not come across anything useful yet. I require a similar function like the one I utilized with highchart: const chart ...