JamesH
JamesH

Reputation: 3

Merge multiple array of objects and average duplicate values javascript

I came across this topic: Merge multiple array of objects and sum duplicate values javascript, and it was so close to something I was trying to do.

I essentially need the same thing, but I need the average of the values instead of the sum. What I thought would do the trick is:

var array1 = [{
    price: "2",
    ref: "A"
  },
  {
    price: "20",
    ref: "B"
  },
  {
    price: "23",
    ref: "C"
  },
  {
    price: "23",
    ref: "D"
  }
];

var array2 = [{
    price: "12",
    ref: "A"
  },
  {
    price: "5",
    ref: "B"
  },
  {
    price: "23",
    ref: "E"
  },
  {
    price: "23",
    ref: "F"
  }
];

var array3 = [{
    name: "Blah",
    fcp: "erol"
  },
  {
    name: "Blah2",
    fcp: "tpep"
  }
];

var averagedArr = 2

var result = array1.concat(array2, array3).reduce(function(acc, curr) {
  if (curr.ref) {
    var fromMap = acc.map[curr.ref];
    if (!fromMap) {
      acc.map[curr.ref] = fromMap = {
        price: 0,
        ref: curr.ref
      }
      acc.result.push(fromMap);
    }
    fromMap.price += parseFloat(curr.price);
    fromMap.price = parseFloat(fromMap.price/averagedArr);
  } else {
    acc.result.push(curr);
  }
  return acc;
}, {
  map: {},
  result: []
}).result;

console.log(result);

It isn't working because it seems to be averaging each price as it is added and not after they have been added all together. For example instead of for ref:B the result being 12.5 (20+5 divided by 2) the result is 7.5 (20/2=10; 10+5=15; 15/2 = 7.5). If anyone could help me figure this out I would be most appreciative.

I would have just commented on the original topic to @Grundy who provided the response I was using, but this is my first question and I can't comment.

Here is the fiddle. https://jsfiddle.net/5xqbk9Lg/

Thanks in advance!

Upvotes: 0

Views: 431

Answers (2)

Nina Scholz
Nina Scholz

Reputation: 386654

You could collect all values in a hash table and create a data set for the result if a new hash entry is created. Later collect price and count and build the average of the actual ref.

var array1 = [{ price: "2", ref: "A" }, { price: "20", ref: "B" }, { price: "23", ref: "C" }, { price: "23", ref: "D" }],
    array2 = [{ price: "12", ref: "A" }, { price: "5", ref: "B" }, { price: "23", ref: "E" }, { price: "23", ref: "F" }],
    array3 = [{ name: "Blah", fcp: "erol" }, { name: "Blah2", fcp: "tpep" }],
    hash = Object.create(null),
    result = [];

[array1, array2, array3].forEach(function (a) {
    a.forEach(function (b) {
        if ('ref' in b) {
            if (!hash[b.ref]) {
                hash[b.ref] = { result: { ref: b.ref, avg: 0 }, sum: 0, count: 0 };
                result.push(hash[b.ref].result);
            }
            hash[b.ref].sum += +b.price,
            hash[b.ref].count++;
            hash[b.ref].result.avg = hash[b.ref].sum / hash[b.ref].count;
        }
    });
});

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

Upvotes: 2

tchatow
tchatow

Reputation: 778

Just change

fromMap.price = parseFloat(fromMap.price/averagedArr);

to

fromMap.finalPrice = parseFloat(fromMap.price/averagedArr);

and use the finalPrice variable as your result. The problem is that you are dividing by averagedArr for every item you add to the price, not just at the end-exactly what you are describing is the error. By using a separate variable to store your final result you aren't diving the sum each time.

Upvotes: 0

Related Questions