【问题标题】:How find sum of all values in object and included objects in array?如何找到对象中所有值的总和以及数组中包含的对象?
【发布时间】:2019-08-02 19:36:27
【问题描述】:

如何找到该对象中所有值的总和?在对象包含的数组中包含另一个具有值的对象,并且可能是具有类似结构对象的“下一个”数组。

{
  value: 4,
  next: [
    {
      value: 3,
      next: [...]
    },
    {
      value: 3,
      next: [...]
    },
    ...
  ]
}

【问题讨论】:

标签: javascript


【解决方案1】:

对象的结构称为树Tree (data structure)。 您可以使用breadth-firstdepth-first 方法对traverse the tree 进行汇总。

其他答案说您必须递归,但您可以使用广度优先方法迭代地执行此操作,我在代码 sn-p 中向您展示了这两种方法。

我已经扩展了你的数据样本,在应该没有下一个值的地方添加了空值(你真的可以使用任何类型的检查)。

let data = {
  value: 4,
  next: [
    {
      value: 3,
      next: [
        {
          value: 5,
          next: null
        },
        {
          value: 6,
          next: null
        }
      ]
    },
    {
      value: 2,
      next: [
        {
          value: 2,
          next: null
        },
        {
          value: 3,
          next: [
            {
              value: 7,
              next: null
            },
            {
              value: 8,
              next: null
            }
          ]
        }
      ]
    }
  ]
}

// iterative approach
function breadthFirst(node){
  let sum = 0
  let q = [node]

  while(q.length > 0){
    let node = q.pop()
    sum += node.value

    if (node.next !== null) {
      for (let other of node.next){
        q.push(other)
      }
    }
  }

  return sum
}

console.log('breadthFirst sum (iterative):', breadthFirst(data))

// recursive apporach
function depthFirst(node){
  let sum = 0

  function recursion(node){
    sum += node.value

    if (node.next !== null) {
      for (let other of node.next){
        recursion(other)
      }
    }
  }

  recursion(node)

  return sum
}

console.log('depthFirst sum (recursive):', depthFirst(data))

【讨论】:

    【解决方案2】:

    使用reduceObject.entries 对这些值进行递归求和:

    const obj = {
      value: 4,
      next: [{
        value: 3,
        next: [{ value: 1 }]
      }, {
        value: 3,
        next: [{ value: 2, next: [] }]
      }]
    };
    
    const sum = (obj) =>
      Object.entries(obj).reduce((acc, [k, v]) => acc + (
        k === 'next'
          ? v.map(sum).reduce((s, x) => s + x, 0)
          : k === 'value' ? v : 0)
      , 0);
    
    console.log(sum(obj));

    【讨论】:

      【解决方案3】:

      您需要递归来处理对象的任意嵌套:

      const nestedSum = o => (o.next || []).reduce((acc, o) => acc + nestedSum(o), o.value);
      
      // Demo
      const data = {
        value: 4,
        next: [{
            value: 3,
            next: [{value: 5}]
          }, {
            value: 3,
            next: []
          },
        ]
      };
      
      console.log(nestedSum(data));

      【讨论】:

      • 如果将 next:[] 更改为 next: [{value:5}] 似乎不正确
      • 我在 sn-p 中添加了这个案例。
      • @trincot 你能让我解释一下o.value 的情况吗?我怎么看首先我们检查是否有数组,用于reduce,然后我们使用递归,然后我不明白那部分, o.value :)
      • o.value 作为第二个参数传递给reduce,以便通过回调累积的总和以该值开始(而不是从 0 开始)。我们当然可以传递 0,然后将 o.value 添加到 reduce 的返回值,但这只是一个额外的操作。最好直接以o.value 开头。
      【解决方案4】:

      function sum(obj, current = 0) {
         const nextSum = (obj.next || []).reduce((nextSum, obj) => nextSum + sum(obj, current), 0)
         return current + nextSum + obj.value
      }
      
      const example = {
        value: 4,
        next: [
          {
            value: 3,
            next: [{
              value: 7
            }]
          },
          {
            value: 3
          }
        ]
      }
      
      console.log(sum(example)) // must be 17

      【讨论】:

        【解决方案5】:

        您需要一个递归函数并检查键的值是否为数字,然后与变量相加,否则如果它是像next 这样的数组,则遍历它并再次使用新对象调用相同的函数

        let data = {
          value: 4,
          next: [{
              value: 3,
              next: [{
                value: 4
              }, {
                value: 5
              }]
            },
            {
              value: 3,
              next: [{
                value: 2
              }]
            }
          ]
        }
        
        let sum = 0;
        
        function findSum(obj) {
          for (let keys in obj) {
            if (typeof obj[keys] === 'number') {
              sum += obj[keys];
            } else if (Array.isArray(obj[keys]) && obj[keys].length > 0) {
              obj[keys].forEach(function(item) {
                findSum(item)
        
              })
            }
          }
        }
        
        findSum(data);
        console.log(sum)

        【讨论】:

          猜你喜欢
          • 2023-02-07
          • 1970-01-01
          • 2015-05-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多