-1

My problem is pretty straight forward I think, I just can't seem to figure it out. I need to go from an array of objects:

    let testArrays = [
{ "containerType": "2 Gallon", "wasteType": "10000001", "vol": "2 Gallons" },
{ "containerType": "2 Gallon", "wasteType": "10000001", "vol": "2 Gallons" },
{ "containerType": "2 Gallon", "wasteType": "10000002", "vol": "2 Gallons" },
{ "containerType": "2 Gallon", "wasteType": "10000002", "vol": "2 Gallons" },
{ "containerType": "2 Gallon", "wasteType": "10000003", "vol": "2 Gallons" },
{ "containerType": "5 Gallon", "wasteType": "10000003", "vol": "5 Gallons" },
{ "containerType": "5 Gallon", "wasteType": "10000003", "vol": "5 Gallons" },
{ "containerType": "5 Gallon", "wasteType": "10000003", "vol": "5 Gallons" },
{ "containerType": "5 Gallon", "wasteType": "10000004", "vol": "5 Gallons" }
]   

To a grouped object with arrays inside, grouped by "wasteType" above with counts. The volume would be created by multiplying the count by the value in "vol", which I can get with parsefloat I believe :

    let wastes = {
        "10000001": [
            {
                "containerType": "2 Gallon",
                "count": 2,
                "vol": "4 Gallons"
            }
        ],
        "10000002": [
            {
                "containerType": "2 Gallon",
                "count": 2,
                "vol": "4 Gallons"
            }
        ],
        "10000003": [
            {
                "containerType": "1 Gallon",
                "count": 1,
                "vol": "2 Gallons"
            },
            {
                "containerType": "5 Gallon",
                "count": 3,
                "vol": "15 Gallons"
            }
        ],
        "10000004": [
            {
                "containerType": "5 Gallon",
                "count": 1,
                "vol": "5 Gallons"
            }
        ],
    }

I know I should use array.map() for this but I am not sure how to do it. I have looked for this specific example everywhere and can't find it. All help is greatly appreciated.

  • Welcome to Stackoverflow, please read [How To Ask](https://stackoverflow.com/help/how-to-ask). Pay special attention to [How To Create MCVE](https://stackoverflow.com/help/mcve). Make sure you tag your question with proper labels (programming language, relevant technologies etc). The more effort you'll put into posting a good question: one which is easy to read, understand and which is [on topic](https://stackoverflow.com/help/on-topic) - the chances are higher that it will attract the relevant people and you'll get help even faster. Good luck! – Nir Alfasi Aug 29 '19 at 18:46
  • Hi @alfasin I apologize, I've asked a fair amount of questions on SO, I thought this one gave enough information but maybe not?. Unfortunately it's a process question that I am not really sure how to get from point A to point B so I figured including things I tried would be more harmful than helpful. Thank you for the info and suggestions. I'll try to improve my questions going forward. – ptrugby4141 Aug 29 '19 at 18:49
  • 1
    Possible duplicate of [Most efficient method to groupby on an array of objects](https://stackoverflow.com/questions/14446511/most-efficient-method-to-groupby-on-an-array-of-objects) – benvc Aug 29 '19 at 19:16

3 Answers3

2

You need to use reduce instead of map

  • Loop through array use wasteType as property name
  • If property is already not on output object initialize with current elements values
  • Increase count by 1
  • Loop over the final again in order to get vol, which is count * vol

let testArrays = [{"containerType": "2 Gallon","wasteType": "10000001","vol": "2 Gallons"}, {"containerType": "2 Gallon","wasteType": "10000001","vol": "2 Gallons"}, {"containerType": "2 Gallon","wasteType": "10000002","vol": "2 Gallons"}, {"containerType": "2 Gallon","wasteType": "10000002","vol": "2 Gallons"}, {"containerType": "2 Gallon","wasteType": "10000003","vol": "2 Gallons"}, {"containerType": "5 Gallon","wasteType": "10000003","vol": "5 Gallons"}, {  "containerType": "5 Gallon","wasteType": "10000003","vol": "5 Gallons"}, {"containerType": "5 Gallon","wasteType": "10000003","vol": "5 Gallons"}, {"containerType": "5 Gallon","wasteType": "10000004","vol": "5 Gallons"}]

let final = testArrays.reduce((op, { containerType, wasteType,vol}) => {
  let obj = { containerType, vol, count: 0 }
  op[wasteType] = op[wasteType] || new Map([[containerType,obj]])
  if(op[wasteType].has(containerType)){
    op[wasteType].get(containerType).count++
  } else{
    obj.count++
    op[wasteType].set(containerType, obj)
  }
  return op
}, {})

for(let key in final){
  final[key] = [...final[key].values()].map(value=>{
  let { containerType, vol, count} = value
  let finalVol = (vol.replace(/[.\D+]/g, '') * count) + " Gallons"
   return { containerType, vol:finalVol, count }
  })
}

console.log(final)
Code Maniac
  • 37,143
  • 5
  • 39
  • 60
  • 1
    That gets me the object perfectly! I will mark this as correct right now. You don't by chance have any idea how to display this new object as a grouped table by looping through it with a v-for statement in Vue? The program I am working in uses Vue in the html template, I'm not sure how to display this data.If not, no worries, you have already helped like crazy! – ptrugby4141 Aug 29 '19 at 19:54
  • @ptrugby4141 sorry to say but i haven't worked on `vue` so far so doesn't know much, but yes this will be easy to do if you follow the docs, they have loop as you're saying `v-for`, `v-of` you can use them – Code Maniac Aug 29 '19 at 19:58
0

@Code Maniac was faster than me, here is my not quite as sophisticated attempt:

testArrays.forEach(el => {
const temp = wastes[el.wasteType];
if (temp) {
    temp.count++;
    temp.vol += el.vol;
} else {
    wastes[el.wasteType] = {
        "containerType": el.containerType,
        "count": 1,
        "vol": el.vol,
    }
}

})

It seems though he didnt noticed that you want to add up the vols too, for that I would remove the unit "Gallons" (maybe add it to the key name) - If you would want to keep it you would have to do some string manipulation, i.e. get the length of the value, subtract the length of " Gallons" and get the substring of the first remaining chars, convert to number, add numbers and add " Gallons" again.

Teiem
  • 1,329
  • 15
  • 32
0

You can simply achieve this with one for loop. What I did here in that loop, I take an one object and check if the value of wasteType Is present in object, If not found then add it along with count:1 initially, If found then check for containerType in that array, If it's also found then incremental it's count with 1.

const array = [{
    "containerType": "2 Gallon",
    "wasteType": "10000001",
    "vol": "2 Gallons"
}, {
    "containerType": "2 Gallon",
    "wasteType": "10000001",
    "vol": "2 Gallons"
}, {
    "containerType": "2 Gallon",
    "wasteType": "10000002",
    "vol": "2 Gallons"
}, {
    "containerType": "2 Gallon",
    "wasteType": "10000002",
    "vol": "2 Gallons"
}, {
    "containerType": "2 Gallon",
    "wasteType": "10000003",
    "vol": "2 Gallons"
}, {
    "containerType": "5 Gallon",
    "wasteType": "10000003",
    "vol": "5 Gallons"
}, {
    "containerType": "5 Gallon",
    "wasteType": "10000003",
    "vol": "5 Gallons"
}, {
    "containerType": "5 Gallon",
    "wasteType": "10000003",
    "vol": "5 Gallons"
}, {
    "containerType": "5 Gallon",
    "wasteType": "10000004",
    "vol": "5 Gallons"
}]

const getUniqueArray = (array) => {
    const tempObj = {};
    for (let i = 0; i < array.length; i += 1) {
            const {
                    containerType,
                    wasteType,
                    vol
            } = array[i];
            const obj = {
                    containerType,
                    count: 1,
                    vol,
            };
            const currentVol = +(vol.split(' ')[0]);
            if (tempObj[wasteType]) {
                    const index = tempObj[wasteType].findIndex((r) => {
                            return r.containerType === containerType;
                    });

                    if (index === -1) {
                            tempObj[wasteType].push(obj);
                    } else {
                            tempObj[wasteType][index].count += 1;
                            const foundVol = tempObj[wasteType][index].vol;
                            const fVol = +(foundVol.split(' ')[0]);
                            const newVol = currentVol + fVol;

                            tempObj[wasteType][index].vol = `${newVol} Gallons`;
                    }
            } else {
                    tempObj[wasteType] = [obj];
            };
    }
    return tempObj;
};

const result = getUniqueArray(array);
console.log(result);
Neel Rathod
  • 2,013
  • 12
  • 28