使用 reduce 遍历 JSON

Using reduce to loop through JSON

我正在使用一个 reduce 函数,它循环遍历我的 JSON 文件并将我指定的键值加在一起。

这工作正常,直到我删除其中一个值。

我的 JSON 是:

[{
        "id": 100,
        "jobNumber": 1,
        "jobTasks": [{
                "id": 12,
                "cost": {
                    "amountString": 100
                }
            },
            {
                "id": 13,
                "cost": {
                    "amountString": 500
                }
            }
        ]
    },
    {
        "id": 101,
        "jobNumber": 2,
        "jobTasks": [{
                "id": 14,
                "cost": {
                    "amountString": 100
                }
            },
            {
                "id": 15
            }
        ]
    }
]

我使用的 reduce 函数是:

json.data.forEach(function(item) {
var sum = item.jobTasks.reduce(function(sum, elem) {
    return sum + elem.cost.amountString;
}, 0);
console.log('jobNumber' + item.jobNumber + ' ' + sum);
});

我正在努力实现这一目标:

jobNumber1 600
jobNumber2 100

如果我在第二份工作中放置另一个 cost.amountString,这将正常工作,但是如我的 [= 中所示,第一个和第二个中有两个34=] 以上,我得到以下错误:

TypeError: Cannot read property 'amountString' of undefined

reduce 是否需要多个或相同数量的值对才能工作?我试过各种for循环都没有成功。

您需要检查没有 属性 amountString 的第二个对象的 undefined 值。如果 属性 amountString 不存在于对象中,则 return 值 0.

因此将 return 语句从
更改为 return sum + elem.cost.amountString;

return sum + (elem.cost && elem.cost.amountString ? elem.cost.amountString : 0) ;

完整代码:

var json = {};
json.data = [{
        "id": 100,
        "jobNumber": 1,
        "jobTasks": [{
                "id": 12,
                "cost": {
                    "amountString": 100
                }
            },
            {
                "id": 13,
                "cost": {
                    "amountString": 500
                }
            }
        ]
    },
    {
        "id": 101,
        "jobNumber": 2,
        "jobTasks": [{
                "id": 14,
                "cost": {
                    "amountString": 100
                }
            },
            {
                "id": 15
            }
        ]
    }
]


json.data.forEach(function(item) {
var sum = item.jobTasks.reduce(function(sum, elem) {
    return sum + (elem.cost && elem.cost.amountString ? elem.cost.amountString : 0) ;
}, 0);
console.log('jobNumber' + item.jobNumber + ' ' + sum);
});

TypeError: Cannot read property 'amountString' of undefined

发生这种情况是因为您正试图取消引用未定义的值。您实际上是在写 return sum + undefined.amountString,这与写 return sum + null.amountString 类似。你如何解决这个问题?

除了 Agalo 的建议之外,我们还可以过滤确实有成本的 jobTask 对象:

json.data.forEach(function(item) {

    var sum = item.jobTasks
      .filter(function (j) { return j.cost; })
      .reduce(function(sum, elem) {

        return sum + elem.cost.amountString;

    }, 0);

    console.log('jobNumber' + item.jobNumber + ' ' + sum);

});

顺便说一句,考虑使用箭头语法,因为它可以说更具可读性。

json.data.forEach((item) => {

    var sum = item.jobTasks
      .filter((j) => j.cost)
      .reduce((sum, elem) => sum + elem.cost.amountString, 0);

    console.log('jobNumber' + item.jobNumber + ' ' + sum);

});

完整代码清单:

var json = {};
json.data = [{
    "id": 100,
    "jobNumber": 1,
    "jobTasks": [{
        "id": 12,
        "cost": {
          "amountString": 100
        }
      },
      {
        "id": 13,
        "cost": {
          "amountString": 500
        }
      }
    ]
  },
  {
    "id": 101,
    "jobNumber": 2,
    "jobTasks": [{
        "id": 14,
        "cost": {
          "amountString": 100
        }
      },
      {
        "id": 15
      }
    ]
  }
];

// with traditional functions
json.data.forEach(function(item) {

  var sum = item.jobTasks
    .filter(function(j) {
      return j.cost;
    })
    .reduce(function(sum, elem) {

      return sum + elem.cost.amountString;

    }, 0);

  console.log('jobNumber' + item.jobNumber + ' ' + sum);

});

// with arrow functions
json.data.forEach((item) => {

  var sum = item.jobTasks
    .filter((j) => j.cost)
    .reduce((sum, elem) => sum + elem.cost.amountString, 0);

  console.log('jobNumber' + item.jobNumber + ' ' + sum);

});