Hman
Hman

Reputation: 393

array need to remove duplicate object based on key value pair and also return sum [fiddle]

need to remove duplicate objects based on matching keys but add values. have created snippet and fiddle to take a look at. Also have added the expected result at the bottom.

I have tried few different things but unable to get desired results. I can use filter method but then cannot add values for matching keys. Please take a look at fiddle or snippet

fiddle link here

  let data2 = [{
        area: {
          type: "double",
          value: 50
        },
        areaName: {
          type: "string",
          value: "westside"
        },
        areaTitle: {
          type: "string",
          value: "rock"
        }
      },
      {
        area: {
          type: "double",
          value: 250
        },
        areaName: {
          type: "string",
          value: "north"
        },
        areaTitle: {
          type: "string",
          value: "sand"
        }
      },
      {
        area: {
          type: "double",
          value: 400
        },
        areaName: {
          type: "string",
          value: "westside"
        },
        areaTitle: {
          type: "string",
          value: "rock"
        }
      }
    ];

    var filterData2 =    Object.keys(data2).reduce((acc, elem) => {
      let getKeys = data2[elem];
      console.log(getKeys);

      return acc;
    }, []);

    console.log(filterData2);



    // Expected result  
    let result = [{
        Area: {
          type: "double",
          value: 450
        },
        AreaName: {
          type: "string",
          value: "westside"
        },
        AreaTitle: {
          type: "string",
          value: "rock"
        }
      },
      {
        Area: {
          type: "double",
          value: 250
        },
        AreaName: {
          type: "string",
          value: "north"
        },
        AreaTitle: {
          type: "string",
          value: "sand"
        }
      }
    ]

    console.log(result);

Upvotes: 3

Views: 76

Answers (3)

malarres
malarres

Reputation: 2946

A solution with find:

let data2 = [{
        area: {
          type: "double",
          value: 50
        },
        areaName: {
          type: "string",
          value: "westside"
        },
        areaTitle: {
          type: "string",
          value: "rock"
        }
      },
      {
        area: {
          type: "double",
          value: 250
        },
        areaName: {
          type: "string",
          value: "north"
        },
        areaTitle: {
          type: "string",
          value: "sand"
        }
      },
      {
        area: {
          type: "double",
          value: 400
        },
        areaName: {
          type: "string",
          value: "westside"
        },
        areaTitle: {
          type: "string",
          value: "rock"
        }
      }
    ];


    let result = [];
    let found = null;
    data2.forEach( x => {
        found = result.find( y => x.areaName.value === y.areaName.value && x.areaTitle.value === y.areaTitle.value);
        if (found){
            found.area.value += x.area.value;
        } else {
// option1: simple
//          result.push(x);
// option2: controlling side effects
            result.push({ 
              area: { value: x.area.value, type: x.area.type }, 
              areaName: x.areaName, 
              areaTitle:x.areaTitle 
            });
        }
    });


    // Expected result  
    let expected = [{
        Area: {
          type: "double",
          value: 450
        },
        AreaName: {
          type: "string",
          value: "westside"
        },
        AreaTitle: {
          type: "string",
          value: "rock"
        }
      },
      {
        Area: {
          type: "double",
          value: 250
        },
        AreaName: {
          type: "string",
          value: "north"
        },
        AreaTitle: {
          type: "string",
          value: "sand"
        }
      }
    ]

    console.log(result,expected);

Upvotes: 1

Karan
Karan

Reputation: 12629

Using reduce & Object.assign() like below you can get desired result. Explanation is added as comment in code.

Note I used Object.assign as curr = Object.assign({}, x); instead of curr = x; because with curr = x; later when we update value while finding existing object it will also update value of data2. Using Object.assign({}, x); this will not happen.

let data2 = [{
    area: {
      type: "double",
      value: 50
    },
    areaName: {
      type: "string",
      value: "westside"
    },
    areaTitle: {
      type: "string",
      value: "rock"
    }
  },
  {
    area: {
      type: "double",
      value: 250
    },
    areaName: {
      type: "string",
      value: "north"
    },
    areaTitle: {
      type: "string",
      value: "sand"
    }
  },
  {
    area: {
      type: "double",
      value: 400
    },
    areaName: {
      type: "string",
      value: "westside"
    },
    areaTitle: {
      type: "string",
      value: "rock"
    }
  }
];

// use reduce to iterate over array and produce result
var result = data2.reduce((a, x) => {
// find matching object from a.
  let curr = a.filter(y => y.areaName.value == x.areaName.value && y.areaTitle.value == x.areaTitle.value)[0];
  // if not exists then create new object and add into a
  // else add value to curr.area.value
  if (!curr) {
    curr = Object.assign({}, x);
    a.push(curr);
  } else {
    curr.area.value += x.area.value;
  }
  // return a
  return a;
}, []);

console.log(result);

Upvotes: 1

Giovanni Esposito
Giovanni Esposito

Reputation: 11156

Ciao, you could try to get distinct areaName.value and then iterate on data2 to sum area.value like:

let data2 = [{
        area: {
          type: "double",
          value: 50
        },
        areaName: {
          type: "string",
          value: "westside"
        },
        areaTitle: {
          type: "string",
          value: "rock"
        }
      },
      {
        area: {
          type: "double",
          value: 250
        },
        areaName: {
          type: "string",
          value: "north"
        },
        areaTitle: {
          type: "string",
          value: "sand"
        }
      },
      {
        area: {
          type: "double",
          value: 400
        },
        areaName: {
          type: "string",
          value: "westside"
        },
        areaTitle: {
          type: "string",
          value: "rock"
        }
      }
    ];
    
    let areas = [...new Set(data2.map(el => el.areaName.value))];
    let result = [];
    areas.forEach(area => {
       let dataToSum = data2.filter(el => el.areaName.value === area)
       let obj = {};
       let areasum = 0
       dataToSum.forEach(el => {
          areasum += el.area.value;
       })
       obj.area = {type: dataToSum [0].area.type, value: areasum}
       obj.areaName = {type: dataToSum [0].areaName.type, value: area}
       obj.areaTitle = {type: dataToSum [0].areaTitle.type, value: dataToSum [0].areaTitle.value}
       result.push(obj)
    })
    console.log(result)
    
    

Upvotes: 1

Related Questions