0

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?

2 Answers 2

2

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);
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the explanation. I'm trying to get this running, but I'm only getting undefined. I took a look at the array again and it's a bit different than I thought it was. I've updated my question above if you're still available to help. Again, thank you for the info!
@ntgCleaner Sure. I've updated my answer. You can just destructure one more level.
Thank you!! I couldn't understand where I was supposed to break down the children in the object, but that's exactly what I was looking for. Thanks!!
1

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

5 Comments

I'm trying to get this running, but I'm only getting undefined. I took a look at the array again and it's a bit different than I thought it was. I've updated my question above if you're still available to help. Again, thank you for the info!
Where does .data() come from? I was extrapolating from your code that data() was an immediate property on each object, but I don't see it in your object structure at all even after the update? (Try posting your exact input in your question when you post your question)
If specs is on the object returned by data, then just do const { count, type } = item.data().specs; instead
data() comes from firestore, I use a path snapshot this.store.collection('users').doc(uid).collection('parts').ref.onSnapshot(result => {} to return result. to get the data, you just run a forEach loop on result: result.forEach(part => { console.log(part.data());} (shown in the third line of the javascript above)
Also, thanks for the tip. I mistyped my data and I apologize for not typing it correctly, although it's not extremely important, just trying to figure out how to access the object's children.

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.