0

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!

1
  • basically, you need a property for the sum of the values and for average keep the sum and build the average in another property. as well as you need a counter for each referece. Commented May 18, 2017 at 6:46

2 Answers 2

2

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; }

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

1 Comment

This looks very cool. I haven't used hash tables before. Will definitely be playing around with this, Thanks.
0

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.

1 Comment

It was apparently too late to even come up with this. Thank you.

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.