Home > Software engineering >  How to create a new object from existing object values in Javascript?
How to create a new object from existing object values in Javascript?

Time:02-16

I am trying to create an object that will be filled with values from an existing object. In my case it should have as result per "Material" an object list with the "Code" and the "Quantity". In addition, if the "Material" and "Code" are the same, the "Quantity" should be summed up. I hope that you can see from my example what I mean. Thanks

const arr = [{
  "Material": "123",
  "Code": "AAA",
  "Quantity": 1
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "456",
  "Code": "CCC",
  "Quantity": 7
}]

var arrResult = [{
  "Material": "123",
  "CodeQuantity": [{
    "Code": "AAA",
    "Quantity": 1
  }, {
    "Code": "BBB",
    "Quantity": 4
  }]
}, {
  "Material": "456",
  "CodeQuantity": [{
    "Code": "CCC",
    "Quantity": 7
  }]
}]

console.log(arr)
console.log("Result:", arrResult)

CodePudding user response:

An approach should consider breaking the OP's entire task into two separate ones.

Within an intermediate step one firstly does reduce the list of material items into a map of (grouped) material items.

The final step does a map-reduce on the values of the intermediate result, where the reduce task is responsible for summing up a material's Code specific Quantity value ...

function collectTotalCodeQuantity(index, item) {
  const { Code, Quantity } = item;

  // access or create the `Code` specific code quantity item.
  const codeQuantityItem = (index[Code] ??= { Code, Quantity: 0 });
  // sum up a `Code` specific code quantity item's quantity value.
  codeQuantityItem.Quantity  = Quantity;

  return index;
}
function createMaterialGroup(index, item) {
  const { Material: materialValue, ...rest } = item;
  // create the `CodeQuantity` key in a more generic way from the
  // `rest` object which is ... `item` data without `Material` property.
  const compoundKey = Object.keys(rest).join('');

  // access or create the `Material` specific group.
  const group = index[materialValue] ??= { Material: materialValue };
  // access or create the `CodeQuantity` specific list.
  const list = group[compoundKey] ??= [];

  // push the `rest` object into the `CodeQuantity` specific list.
  list.push(rest);
  return index;
}

const materialDataItemList = [{
  "Material": "123",
  "Code": "AAA",
  "Quantity": 1
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "456",
  "Code": "AAA",
  "Quantity": 7
}];

const totalCodeQuantityItemList = Object
  .values(
    materialDataItemList.reduce(createMaterialGroup, {})
  )
  .map(materialGroup => {
    materialGroup.CodeQuantity = Object.values(
      materialGroup.CodeQuantity.reduce(collectTotalCodeQuantity, {})
    );
    return materialGroup;
  });

console.log({ totalCodeQuantityItemList });
console.log(
  '... intermediate process result ... map of (grouped) material items ...',
  materialDataItemList.reduce(createMaterialGroup, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

CodePudding user response:

Updated the solution to match your expectation. This this. Hope it solves your use case.

const arr = [{
  "Material": "123",
  "Code": "AAA",
  "Quantity": 1
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "456",
  "Code": "CCC",
  "Quantity": 7
}]

var arrResultExpected = [{
  "Material": "123",
  "CodeQuantity": [{
    "Code": "AAA",
    "Quantity": 1
  }, {
    "Code": "BBB",
    "Quantity": 4
  }]
}, {
  "Material": "456",
  "CodeQuantity": [{
    "Code": "CCC",
    "Quantity": 7
  }]
}]

//console.log(arr)
//console.log("ExpecredResult:", arrResultExpected)

const materialIds = arr.map(a => a.Material);
//console.log(materialIds);
const dedupedMaterialIds = [...new Set(materialIds)]
//console.log(dedupedMaterialIds);

const needArr = dedupedMaterialIds.map(entry => {
  const matchingEntries = arr.filter(arrEntry => entry === arrEntry.Material);
  //console.log(matchingEntries);

  var summedResult = [];
  matchingEntries.reduce(function(res, value) {
    if (!res[value.Code]) {
      res[value.Code] = {
        Quantity: 0,
        Code: value.Code
      };
      summedResult.push(res[value.Code])
    }
    res[value.Code].Quantity  = value.Quantity
    return res;
  }, {});
  //console.log(summedResult);
  return {
    Material: entry,
    CodeQuantity: [...summedResult]
  };
});


console.log(needArr);

CodePudding user response:

try this

const arr = [{
  "Material": "123",
  "Code": "AAA",
  "Quantity": 1
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "123",
  "Code": "BBB",
  "Quantity": 2
}, {
  "Material": "456",
  "Code": "CCC",
  "Quantity": 7
}];

let group = arr.reduce((r, a) => {
  r[a.Material] = [...r[a.Material] || [], a];
  return r;
}, {});



 var newArr = Object.keys(group).map(key => {
        var elem = group[key];
        var b = elem.map(e => {
            return {
                Code: e.Code,
                Quantity: e.Quantity

            }
        });
        var filteredArr = [];
        b.map(i => {
            var item = filteredArr.find(n => n.Code == i.Code);
            if (item) {
                item.Quantity  = i.Quantity;
            } else {
                filteredArr.push(i);
            }
        })
        return {
            Material: key,
            CodeQuantity: filteredArr
        }
    });
    console.log(newArr);
   

  • Related