ntgCleaner
ntgCleaner

Reputation: 5985

Javascript - Making an object and incrementing count in an array for each loop

I am trying to create an object from a forEach loop in javascript and in this simple object, I am trying to add up all of the counts for each item in the array.

Currently, I'm using firebase in an ionic (angular/typescript) project and I am returning an array of items from firebase. The array looks something like this:

[
    {
        id:'uniqueID',
        specs: {
            count:5,
            forSale:false,
            group:"qPELnTnwGJEtJexgP2qX",
            name:"Foxeer Cam 2",
            type:"camera"
        }
    },
    {
        id:'uniqueID',
        specs: {
            count:4,
            forSale:false,
            group:"qPELnTnwGJEtJexgP2qX",
            name:"Furibee 40a",
            type:"esc"
        }
    },
    {
        id:'uniqueID',
        specs: {
            count:4,
            forSale:false,
            group:"qPELnTnwGJEtJexgP2qX",
            name:"Runcam Cam 1",
            type:"camera"
        }
    },
    {
        id:'uniqueID',
        specs: {
            count:1,
            forSale:false,
            group:"qPELnTnwGJEtJexgP2qX",
            name:"Hobbywing 4 in 1",
            type:"esc"
        }
    }
]

Here's how I'm running through these items (result being the list of items):

let partArr = [];
let typeObj = {};
result.forEach(part => {

  //Put all parts in a list
  partArr.push({
    'id':part.id,
    'specs':part.data(),
  });

  //Put all types in a list
  typeObj[part.data().type] = {
    'count': 0
  };

});

Now, I need to increment the count, adding each part's count to the last depending on their type. The typeObj should look something like this.

{
    esc: {
        count:5
    },
    camera: {
        count:10
    }
}

I tried adding the count to the count like so:

  typeObj[part.data().type] = {
    'count': typeObj[part.data().type].count + part.data().count
  };

but it does not recognize there being a count when I'm first making the object. (I think).

Any advice?

Upvotes: 0

Views: 236

Answers (2)

CertainPerformance
CertainPerformance

Reputation: 370729

It would probably be easier to use reduce to generate the object with the counts all at once, and to call .data() only once on each iteration:

const results = [
  {
    data() { return { specs: {
    count:5,
    forSale:false,
    group:"qPELnTnwGJEtJexgP2qX",
    name:"Foxeer Cam 2",
    type:"camera"
  }}}},
  {
    data() { return { specs: {
    count:4,
    forSale:false,
    group:"qPELnTnwGJEtJexgP2qX",
    name:"Furibee 40a",
    type:"esc"
  }}}},
  {
    data() { return { specs: {
    count:4,
    forSale:false,
    group:"qPELnTnwGJEtJexgP2qX",
    name:"Runcam Cam 1",
    type:"camera"
  }}}},
  {
    data() { return { specs: {
    count:1,
    forSale:false,
    group:"qPELnTnwGJEtJexgP2qX",
    name:"Hobbywing 4 in 1",
    type:"esc"
  }}}}
];
const typeObj = results.reduce((a, item) => {
  const { count, type } = item.data().specs;
  if (!a[type]) a[type] = { count: 0 };
  a[type].count += count;
  return a;
}, {});
console.log(typeObj);

Upvotes: 1

Andrew Li
Andrew Li

Reputation: 57954

You can use Array#reduce to accomplish this since you want to transform an array into a single object:

const array = [
  {
    id: 'uniqueID',
    specs: {
      count: 5,
      forSale: false,
      group: "qPELnTnwGJEtJexgP2qX",
      name: "Foxeer Cam 2",
      type: "camera"
    }
  },
  {
    id: 'uniqueID',
    specs: {
      count: 4,
      forSale: false,
      group: "qPELnTnwGJEtJexgP2qX",
      name: "Furibee 40a",
      type: "esc"
    }
  },
  {
    id: 'uniqueID',
    specs: {
      count: 4,
      forSale: false,
      group: "qPELnTnwGJEtJexgP2qX",
      name: "Runcam Cam 1",
      type: "camera"
    }
  },
  {
    id: 'uniqueID',
    specs: {
      count: 1,
      forSale: false,
      group: "qPELnTnwGJEtJexgP2qX",
      name: "Hobbywing 4 in 1",
      type: "esc"
    }
  }
];
const typeObj = array.reduce((obj, { specs: { count, type } }) => {
  obj[type] = obj[type] || { count: 0 };
  obj[type].count += count;
  return obj;
}, {});
console.log(typeObj);

What this does is assign obj[type] to either itself or if it doesn't yet exist, a new object { count: 0 }. Then it increments the count property of obj[type] by the specified count in the data.

If you have a data method that returns an object with the data (as you seem to have in the question), you can modify it like so:

const typeObj = array.reduce((obj, item) => {
  const { type, count } = item.data().specs;
  obj[type] = obj[type] || { count: 0 };
  obj[type].count += count;
  return obj;
}, {});
console.log(typeObj);

Upvotes: 2

Related Questions