1

I was having some trouble when trying to sort and group the array items in JavaScript. Here is the sample inputs:

var arr = [
{merchantName: '', branchName: 'e', branchAddress: '', total: 10.5},
];

The output that I am trying to achieve:

var arr = [
{merchantName: '', branchName: '', branchAddress: '', total: 10.5},
];

I wanted to sort it in by branchName, for instance sum up the total for same branchName then at the same time bind all other attributes like merchantName and branchAddress together with it so that I can access them like:

for(var i = 0; i < arr.length; i++){
            console.log(arr[i].merchantName + ' ' + arr[i].branchName + ' ' + arr[i].branchAddress + ' ' + arr[i].total);
        }

I actually have no idea on how to even start it. Any ideas how to achieve it?

3 Answers 3

4

So here is how I would do it:

  1. Group the array into a hashmap based on the branchName property - calculate the total along with this.

  2. Take out the array from the hashmap and sort them

See demo below:

var arr = [
{merchantName: 'Giant', branchName: 'Giant Marine', branchAddress: 'Terrace 56 Branch Blk 56 Marine Terrace #01-259/261 Singapore 440056', total: 10.5},
{merchantName: 'Ntuc', branchName: 'Ntuc Zhongshan Mall Branch', branchAddress: ' Zhongshan Mall Balestier #02-01, 20 Ah Hood Road, 329984', total: 12.149999999999999},
{merchantName: 'Giant', branchName: 'Giant Kim Keat 260 Branch', branchAddress: ' Blk 260 Kim Keat Avenue #01-01 Singapore 310260', total: 5.1},
{merchantName: 'Ntuc', branchName: 'Ntuc Scotts Square Branch', branchAddress: ' Scotts Square #B1-03 To 07 & #B1-10, 6 Scotts Road, 228209', total: 4},
{merchantName: 'Ntuc', branchName: 'Ntuc Zhongshan Mall Branch', branchAddress: ' Zhongshan Mall Balestier #02-01, 20 Ah Hood Road, 329984', total: 4},
{merchantName: 'Ntuc', branchName: 'Ntuc Zhongshan Mall Branch', branchAddress: ' Zhongshan Mall Balestier #02-01, 20 Ah Hood Road, 329984', total: 8}
];

// create a hashmap
var hash = arr.reduce(function(p,c){
  if(!p[c.branchName])
    p[c.branchName] = c;
  else
    p[c.branchName].total += c.total;
  return p;
}, Object.create(null))

// now extract the result and sort them
var result = Object.keys(hash).map(function(e){
   return hash[e];
}).sort(function(a,b){
   return a.branchName - b.branchName;
});

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

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks so much! But how can I extract out the attribute? I tried console.log(result.branchName) but it returns me undefined
Well you should loop through result and do something like result[i].branchName...
I see I see. Thanks so much! But just to double confirm with you as I am trying to understand the code, when you creating hash map, where you reference the p & c parameters? Because from what I understand, you are trying to check if branchName exists, then sum up total. If not create a new object, am I right?
reduce has a functional programming flavor in javascript.. you can check that out :)
2

A solution using reduce()

var arr = [{
    merchantName: 'Giant',
    branchName: 'Giant Marine',
    branchAddress: 'Terrace 56 Branch Blk 56 Marine Terrace #01-259/261 Singapore 440056',
    total: 10.5
  },
  {
    merchantName: 'Ntuc',
    branchName: 'Ntuc Zhongshan Mall Branch',
    branchAddress: ' Zhongshan Mall Balestier #02-01, 20 Ah Hood Road, 329984',
    total: 12.149999999999999
  },
  {
    merchantName: 'Giant',
    branchName: 'Giant Kim Keat 260 Branch',
    branchAddress: ' Blk 260 Kim Keat Avenue #01-01 Singapore 310260',
    total: 5.1
  },
  {
    merchantName: 'Ntuc',
    branchName: 'Ntuc Scotts Square Branch',
    branchAddress: ' Scotts Square #B1-03 To 07 & #B1-10, 6 Scotts Road, 228209',
    total: 4
  },
  {
    merchantName: 'Ntuc',
    branchName: 'Ntuc Zhongshan Mall Branch',
    branchAddress: ' Zhongshan Mall Balestier #02-01, 20 Ah Hood Road, 329984',
    total: 4
  },
  {
    merchantName: 'Ntuc',
    branchName: 'Ntuc Zhongshan Mall Branch',
    branchAddress: ' Zhongshan Mall Balestier #02-01, 20 Ah Hood Road, 329984',
    total: 8
  }
];

var newArr = arr.reduce(function(items, item) {

  var existing = items.find(function(i) {
    return i.branchName === item.branchName;
  });
  
  if (existing) {
    existing.total += item.total;
  } else {
    items.push(item);
  }
  
  return items;
}, []);

console.log(newArr);

Comments

0

Looks like you're wanting to do 2 things: sort by the branchName and then output a single value for each branchName (de-duplicate the results / group-by branchName).

There are a couple of potential issues. 1) your example output shown above isn't sorted by branchName, even though you stated that a) you wanted it to be sorted by branchName, and b) that this would be an example. Second, the output is not entirely deterministic - in particular it seems you just output the first matching record form branchName and thus the value for the total property - which varies among the records for the same branchName - is what is shown. So... assuming you A) want the results sorted, and B) don't care about the value of the "total" attribute, this can be done pretty easily via:

I) Sort the array. See https://gist.github.com/umidjons/9614157 for an example: just write a comparison function that compares branchName values. And, II) Loop through the results, just outputing the first record whenever the branchName changes from the previous value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.