3

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

3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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)
    
    

1 Comment

No problem :) :)
1

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

1 Comment

@Karan i was not controlling side effects. I will edit the answer to give the option to control them

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.