组合具有相同属性的对象

combining objects with the same properties

我有一个对象数组,

let arrPeople = [
                {name: "Jack", expenseType: "food", amount: 50},
                {name: "Kate", expenseType: "food", amount: 60},
                {name: "Rob", expenseType: "transportation", amount: 15},
                {name: "Jack", expenseType: "food", amount: 40},
                {name: "Kate", expenseType: "transportation", amount: 20},
                {name: "Jack", expenseType: "miscellaneous", amount: 30},
                {name: "Rob", expenseType: "transportation", amount: 15}
                ]

我想合并具有相同名称和费用类型的对象并添加金额并保留其他没有相似之处的对象。

预期输出:

let newArr = [
            {name: "Jack", expenseType: "food", amount: 90},
            {name: "Kate", expenseType: "food", amount: 60},
            {name: "Rob", expenseType: "transportation", amount: 30},
            {name: "Kate", expenseType: "transportation", amount: 20},
            {name: "Jack", expenseType: "miscellaneous", amount: 30}
            ]

请发送帮助,谢谢

虽然这个问题被标记为重复,但我发现这个问题的要求略有不同。

这是使用嵌套循环实现它的方法。

遍历数组,以第一个对象为例this对象

{name: "Jack", expenseType: "food", amount: 50},。现在 运行 第二个循环并从数组中找到所有具有相同 name 和相同 expenseType 的对象。如果 name 和 expenseType 相等,则将其他对象的 amount 添加到第一个对象。

接下来将 nameexpenseType 匹配的那些对象的索引设置为 undefined.

这样做的目的是下次使用新数组调用相同的 doReduce 函数,而不是在迭代中包含具有相同 nameexpenseType 的对象。

例如 arrPeople 有两个具有相同 nameexpenseType 的对象。所以我们可以创建一个具有相同名称和费用类型的对象并添加它们的不同 amount 并将这两个对象的索引设置为未定义。

所以会像

let arrPeople = [undefined, {
    name: "Kate",
    expenseType: "food",
    amount: 60
  },
  {
    name: "Rob",
    expenseType: "transportation",
    amount: 15
  },
  undefined,
  {
    name: "Kate",
    expenseType: "transportation",
    amount: 20
  },
  {
    name: "Jack",
    expenseType: "miscellaneous",
    amount: 30
  },
  {
    name: "Rob",
    expenseType: "transportation",
    amount: 15
  }
]
`

不,我再次通过删除重复项使用新数组调用 doReduce 函数。

工作示例

let arrPeople = [{
    name: 'Jack',
    expenseType: 'food',
    amount: 50
  },
  {
    name: 'Kate',
    expenseType: 'food',
    amount: 60
  },
  {
    name: 'Rob',
    expenseType: 'transportation',
    amount: 15
  },
  {
    name: 'Jack',
    expenseType: 'food',
    amount: 40
  },
  {
    name: 'Kate',
    expenseType: 'transportation',
    amount: 20
  },
  {
    name: 'Jack',
    expenseType: 'miscellaneous',
    amount: 30
  },
  {
    name: 'Rob',
    expenseType: 'transportation',
    amount: 15
  }
];
//
function doReduce(arr, finalArr) {
  // iterate through entire length of the array;
  // take first element of the array and find same object from the arry which have same name and same expense type 
  for (let i = 0; i < arr.length; i++) {
    for (let j = 1; j < arr.length; j++) {
      // if the expense type and name matches then the amount can be added to the first object of the array
      if (arr[i].name === arr[j].name && arr[i].expenseType === arr[j].expenseType) {
        arr[i].amount += arr[j].amount;
        // setting undefined
        arr[j] = undefined
      }
    }
    finalArr.push(arr[i]);
    arr[i] = undefined;
    // remove all undefined from the array
    const newArr = arr.filter(item => item !== undefined);
    // get all object which are not undefined and call recall doReduce with new array set
    if (newArr.length > 0) {
      return doReduce(newArr, finalArr)
    } else {
      return finalArr
    }
  }
}
console.log(doReduce(arrPeople, []));

稍微压缩代码

let arrPeople = [{
    name: 'Jack',
    expenseType: 'food',
    amount: 50
  },
  {
    name: 'Kate',
    expenseType: 'food',
    amount: 60
  },
  {
    name: 'Rob',
    expenseType: 'transportation',
    amount: 15
  },
  {
    name: 'Jack',
    expenseType: 'food',
    amount: 40
  },
  {
    name: 'Kate',
    expenseType: 'transportation',
    amount: 20
  },
  {
    name: 'Jack',
    expenseType: 'miscellaneous',
    amount: 30
  },
  {
    name: 'Rob',
    expenseType: 'transportation',
    amount: 15
  }
];

function doReduce(arr, finalVal) {
  // Note unlike other code, not adding i++, since it is never used
  for (; 0 < arr.length;) {
    for (let b = 1; b < arr.length; b++) {
      arr[0].name === arr[b].name && arr[0].expenseType === arr[b].expenseType && (arr[0].amount += arr[b].amount, arr[b] = void 0);
    }
    finalVal.push(arr[0]);
    arr[0] = void 0;
    b = arr.filter(function(d) {
      return void 0 !== d;
    });
    return 0 < b.length ? doReduce(b, finalVal) : finalVal;
  }
}
console.log(doReduce(arrPeople, []));