-4

I have an array of objects that looks like this:

[{
date: "07-14-2022",
  report: [{
    vehicles: [{
      id: "uid",
      status: "active",
      type: "car"
    },
    {
      id: "uid",
      status: "oos",
      type: "bus"
    },
    {
      id: "uid",
      status: "pm",
      type: "bus"
    }
    ]
  }]
}]

I'm trying to achieve excluding any status other than "oos" or "pm" (was thinking about first using filter here for the first stage). And then I needed to group all the unique values for type so I could provide a breakdown of total numbers for each. So, in the end it would look like:

bus: 2

This is the first stage I was starting to work on, but having trouble...

  getReport() {
    this.backend.getAnalyticsReport().subscribe(
      response => {
        console.log(this.processReport(response))
      }
    )

    
  }

  processReport(obj: any) {
    return obj.filter((element: any) => this.filterStatus(element.vehicles))
  }

  filterStatus(element: any) {

    if (element.status === 'oos' || 'pm') { 
      return true
    } else {
      return false
    }
  }
Daniel
  • 53
  • 2
  • 8
  • the correct condition would simply be `['oos', 'pm'].includes(element.status)`. the current condition will always be _truthy_, as it would evaluate to `'pm'` if the status isn't `'oos'` – don_aman Jul 14 '22 at 21:34
  • or `element.status === 'oos' || element.status === 'pm'`. see: [What's the prettiest way to compare one value against multiple values?](https://stackoverflow.com/questions/9121395/whats-the-prettiest-way-to-compare-one-value-against-multiple-values) – pilchard Jul 14 '22 at 21:36
  • @Daniel what exactly does your `response` look like? – lukasl-dev Jul 14 '22 at 21:49

2 Answers2

0

filter first then use reduce to group. This is a trick I've learned from this answer

var data = [{
    id: "uid",
    status: "active",
    type: "car"
  },
  {
    id: "uid",
    status: "oos",
    type: "bus"
  },
  {
    id: "uid",
    status: "pm",
    type: "bus"
  }
]

var result = data
  .filter(item => ['oos', 'pm'].indexOf(item.status) > -1)
  .reduce(function(agg, item) {
    agg[item.type] = (agg[item.type] || 0) + 1
    return agg;
  }, {})
console.log(result)
IT goldman
  • 14,885
  • 2
  • 14
  • 28
  • This solution worked for me -- because this object is within another object, I made this a function and called the method in a nested *ngFor loop and then used the keyvalue pipe to display the keys as table header and the values as the cells. – Daniel Jul 14 '22 at 22:45
0

You could do something like this using the Array.reduce() and Array.includes() methods. I modified the data to add in extra car calues that would be counted and added in an extra date to demonstrate how you could get the counts by day.

const data = [{
    date: "07-14-2022",
    report: [{
      vehicles: [{
          id: "uid",
          status: "active",
          type: "car"
        },
        {
          id: "uid",
          status: "oos",
          type: "bus"
        },
        {
          id: "uid",
          status: "pm",
          type: "bus"
        },
        {
          id: "uid",
          status: "pm",
          type: "car"
        },
        {
          id: "uid",
          status: "active",
          type: "bus"
        }
      ]
    }]
  },
  {
    date: "07-15-2022",
    report: [{
      vehicles: [{
          id: "uid",
          status: "active",
          type: "car"
        },
        {
          id: "uid",
          status: "oos",
          type: "car"
        },
        {
          id: "uid",
          status: "pm",
          type: "bus"
        },
        {
          id: "uid",
          status: "pm",
          type: "bus"
        },
        {
          id: "uid",
          status: "active",
          type: "bus"
        }
      ]
    }]
  }
];

const types = ["oos", "pm"];

const results = data.reduce((a, c) => {
  a[c.date] = c.report[0].vehicles.reduce((a2, c2) => {
    if (types.includes(c2.status)) {
      a2[c2.type] ??= 0;
      a2[c2.type]++;
    }
    return a2;
  }, {})
  return a
}, {});

document.querySelector('pre').innerText = JSON.stringify(results, null, 3);
<pre></pre>
Steve
  • 878
  • 1
  • 5
  • 9