1

I have a reduce function that is building multiple levels and is working perfectly for me except for one issue

Currently, it's building data based on employee first, then by date, area, and job. I'm getting all of the data at the proper level but I'm now trying to aggregate certain data for a totals section at the date level and it's just listing values rather than aggregating.

Basically, in the line I've notated below, I'd like to create a value called total_scans that simply adds up ALL scans for any orders on that date. In other words, for the record for Miranda on 8/12 I would expect the total_scans at the date level to have 49 as the value. Am I on the right track?

const nest = (rows) =>
  rows.reduce(
    (a, row) => {
      const employee = a[row.employee] || (a[row.employee] = { dates: {} })
      const date = employee.dates[row.job_date] || (employee.dates[row.job_date] = { areas: {} })
      const order = date.areas[row.area_number] || (date.areas[row.area_number] = { jobs: {} })
      const job = order.jobs[row.job] || (order.jobs[row.job] = { hours: '', scans: '', job_date: '' })

      job.hours += row.hours
      job.scans += row.scans
      job.job_date = row.job_date
      
      //this line is my issue
      date.total_scans += job.scans

      return a
    },
    {}
  );

new Vue({
  el: "#app",
  props: {

  },
  data: {
    rows: [
      {
        employee: "Miranda",
        job: "123",
        hours: "10",
        job_date: "08/12/2021",
        scans: 37,
        area_number: "1234567",

      },
      {
        employee: "Miranda",
        job: "167",
        hours: "15",
        scans: 12,
        job_date: "08/12/2021",
        area_number: "1234568",

      },
      {
        employee: "Miranda",
        job: "184",
        hours: "18",
        scans: 24,
        job_date: "08/13/2021",
        area_number: "1234569",

      }
    ],
  },
  computed: {

    numbersByEmployee() {
      return nest(this.rows)
    },
    
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>


<div id="app">
{{numbersByEmployee}}
</div>

3
  • you're returning a which appears to be an array, from reduce, when you should be returning the sum, a Number. Commented Aug 26, 2021 at 5:54
  • try returning date.total_scans Commented Aug 26, 2021 at 5:56
  • you also probably want to filter by date Commented Aug 26, 2021 at 6:01

1 Answer 1

0

Your usage of reduce is a little irregular. The idea of reduce is to take an iterable (array) and return a single value, usually something like a String or Number.

Also, you're causing all sorts of side effects in your reducer, by modifying the object and arrays. Since Javascript is pass-by-reference for arrays and objects, those changes you're causing will be reflected in the original object, which is not how Vue prescribes things are done. If you want to modify data, it should be done in a watch, not a computed.

Finally, I believe you're overcomplicating your reduce function. Instead of a long reduce like that, you could simply do the below. Note the initialValue of 0.

const nest = (rows) =>
  rows.reduce(
    (sum, row) => {
       return sum + row['scans'];          
    },
    0
  );

Obviously this will count all scans. If you want to only count scans by date, how about save yourself running the reducer across the array, and instead run filter first? Something like

const nest = (rows) => 
  rows.filter(({job_date}) => job_date === SomeDate).reduce(...)

The {job_date} is a destructuring assignment. You could also split out a date filtered array into its own computed.

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

2 Comments

Your answer does make sense, and I was able to test that previously, but the issue is that I need the new array in that structure which is why I was using reduce that way and returning "a". My issue was that I wanted to try and add the total field at the date level of the array, since I'm already mapping by date anyway
So basically I need what I'm currently returning (in that structure) but I just need the total at the date level as well

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.