如何从现有条目创建新对象?

How to create a new object from existing entries?

我正在尝试创建一个对象,该对象将填充现有对象的值。在我的例子中,它应该根据“Material”得到一个包含“代码”和“数量”的对象列表。另外,如果“Material”和“Code”相同,则“Quantity”要相加。 我希望你能从我的例子中明白我的意思。谢谢

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)

试试这个

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

更新了解决方案以符合您的期望。 这这。希望它能解决您的用例。

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

一种方法应该考虑将 OP 的整个任务分成两个单独的任务。

在中间步骤中,首先将 reduce material 项的列表转换为(分组的)material 项的映射。

最后一步做中间结果的map-reduce on the values,其中reduce任务负责总结material的Code具体Quantity 值 ...

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

编辑

Moin! how can I add a new key "CodeQuantityGesamt" where the values of all "Quantity" of a "Material" is summed? example:

{
  "Material": "123",
  "CodeQuantityGesamt": 5,
  "CodeQuantity": [{
    "Code": "AAA",
    "Quantity": 1
  }, {
    "Code": "BBB",
    "Quantity": 4
  }]
}

– InFlames82

这可以通过改变映射任务来实现...

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

...例如...

.map(materialGroup => Object.assign(
  materialGroup,
  materialGroup.CodeQuantity.reduce(collectCodeQuantityTotals, {})
));

... 调整实现并更改前 collectTotalCodeQuantity reducer 函数的名称,该函数变为 collectCodeQuantityTotals.

function collectCodeQuantityTotals(quantities, item, idx, arr) {
  const { Code, Quantity } = item;
  let {
    CodeQuantityTotal = 0,
    CodeQuantity = [],
    index = {},
  } = quantities;

  // access ...
  let codeQuantityItem = index[Code];
  // ... or create the `Code` specific code quantity item.
  if (!codeQuantityItem) {
    codeQuantityItem = index[Code] = { Code, Quantity: 0 };

    // push a newly created item into the CodeQuantity list.
    CodeQuantity.push(codeQuantityItem);
  }
  // sum up a `Code` specific code quantity item's quantity value.
  codeQuantityItem.Quantity += Quantity;

  // sum up the total (or overall) code quantity value.
  CodeQuantityTotal += Quantity;

  // return a full collector/accumulator object as long as
  // the reduce task takes place because `index` is needed
  // as lookup, but return, as the final result, an object
  // without the `index` property.
  return (idx < arr.length - 1)
    && { CodeQuantityTotal, CodeQuantity, index }
    || { CodeQuantityTotal, CodeQuantity };
}
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 => Object.assign(
    materialGroup,
    materialGroup.CodeQuantity.reduce(collectCodeQuantityTotals, {})
  ));

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