javascript - 如何从基于对象数组内部的对象数组返回值的总和

标签 javascript arrays object ecmascript-6

我有以下示例对象数组,数组中的每个对象都包含一个 idpersonIdscores 以及最后的 得分。在某些对象中,scores 要么为 null,要么包含另一个作为分数的对象数组。在其他对象中,score 可能包含一个值,而不是 null。最后,可能存在对象可以同时包含 scoresscore 的情况。

const startingArray = [
  {
    id: 1,
    personId: 1,
    scores: [
      {
        id: 1,
        title: 'Google',
        score: 12
      },
      {
        id: 2,
        title: 'Bing',
        score: 23
      },
      {
        id: 3,
        title: 'Facebook',
        score: 34
      }
    ],
    score: null
  },
  {
    id: 2,
    personId: 1,
    scores: null,
    score: 123
  },
  {
    id: 3,
    personId: 2,
    scores: [
      {
        id: 4,
        title: 'Google',
        score: 7
      },
      {
        id: 5,
        title: 'Bing',
        score: 32
      },
      {
        id: 6,
        title: 'Facebook',
        score: 9
      }
    ],
    score: null
  },
  {
    id: 4,
    personId: 3,
    scores: null,
    score: 106
  },
  {
    id: 5,
    personId: 3,
    scores: [
      {
        id: 7,
        title: 'Google',
        score: 6
      },
      {
        id: 8,
        title: 'Bing',
        score: 4
      },
      {
        id: 9,
        title: 'Facebook',
        score: 3
      }
    ],
    score: 5
  }
]

我可以过滤 startingArray 以返回一个人的有效对象:

startingArray.filter(item => item.personId === personId)

我还弄清楚了如何使用 mapreduce 来返回该人的 score 项的值:

startingArray.filter(item => item.personId === personId).map(item => item.score).reduce((a, b) => a + b, 0)

我正在努力的地方是能够对针对一个人设置的 scores 数组中的 score 项进行求和。

最终我想要的是能够调用 personScores(1) 并返回第 1 个人的总分(即 69),或者调用 personScores(3 ) 它将返回 124(即 106 + 13 + 5)。

最佳答案

尚不清楚一个人是否可以在 startingArray 中出现多次。假设它们可以出现多次:

一种流行的方法是使用Array#reduce,但我只使用几个for-of循环。您不需要预先过滤(尽管有些人更喜欢这样做,这很好)。

这是for-of版本:

function personScore(personId) {
  let sum = 0;
  for (const entry of startingArray) {
    if (entry.personId === personId) {
      sum += entry.score || 0;
      if (entry.scores) {
        for (const {score} of entry.scores) {
          sum += score;
        }
      }
    }
  }
  return sum;
}

实时复制:

const startingArray = [
  {
    id: 1,
    personId: 1,
    scores: [
      {
        id: 1,
        title: 'Google',
        score: 12
      },
      {
        id: 2,
        title: 'Bing',
        score: 23
      },
      {
        id: 3,
        title: 'Facebook',
        score: 34
      }
    ],
    score: null
  },
  {
    id: 2,
    personId: 1,
    scores: null,
    score: 123
  },
  {
    id: 3,
    personId: 2,
    scores: [
      {
        id: 4,
        title: 'Google',
        score: 7
      },
      {
        id: 5,
        title: 'Bing',
        score: 32
      },
      {
        id: 6,
        title: 'Facebook',
        score: 9
      }
    ],
    score: null
  },
  {
    id: 4,
    personId: 3,
    scores: null,
    score: 106
  },
  {
    id: 5,
    personId: 3,
    scores: [
      {
        id: 7,
        title: 'Google',
        score: 6
      },
      {
        id: 8,
        title: 'Bing',
        score: 4
      },
      {
        id: 9,
        title: 'Facebook',
        score: 3
      }
    ],
    score: 5
  }
]
function personScore(personId) {
  let sum = 0;
  for (const entry of startingArray) {
    if (entry.personId === personId) {
      sum += entry.score || 0;
      if (entry.scores) {
        for (const {score} of entry.scores) {
          sum += score;
        }
      }
    }
  }
  return sum;
}
console.log(personScore(1));

这是reduce版本:

function personScore(personId) {
  return startingArray.reduce((sum, entry) => {
    if (entry.personId !== personId) {
      return sum;
    }
    sum += entry.score || 0;
    if (entry.scores) {
      sum += entry.scores.reduce((acc, {score}) => acc + score, 0);
    }
    return sum;
  }, 0);
}

实时复制:

const startingArray = [
  {
    id: 1,
    personId: 1,
    scores: [
      {
        id: 1,
        title: 'Google',
        score: 12
      },
      {
        id: 2,
        title: 'Bing',
        score: 23
      },
      {
        id: 3,
        title: 'Facebook',
        score: 34
      }
    ],
    score: null
  },
  {
    id: 2,
    personId: 1,
    scores: null,
    score: 123
  },
  {
    id: 3,
    personId: 2,
    scores: [
      {
        id: 4,
        title: 'Google',
        score: 7
      },
      {
        id: 5,
        title: 'Bing',
        score: 32
      },
      {
        id: 6,
        title: 'Facebook',
        score: 9
      }
    ],
    score: null
  },
  {
    id: 4,
    personId: 3,
    scores: null,
    score: 106
  },
  {
    id: 5,
    personId: 3,
    scores: [
      {
        id: 7,
        title: 'Google',
        score: 6
      },
      {
        id: 8,
        title: 'Bing',
        score: 4
      },
      {
        id: 9,
        title: 'Facebook',
        score: 3
      }
    ],
    score: 5
  }
]
function personScore(personId) {
  return startingArray.reduce((sum, entry) => {
    if (entry.personId !== personId) {
      return sum;
    }
    sum += entry.score || 0;
    if (entry.scores) {
      sum += entry.scores.reduce((acc, {score}) => acc + score, 0);
    }
    return sum;
  }, 0);
}
console.log(personScore(1));

如果它们只能出现一次,数组确实不是组织数据的方式(我会使用对象或 Map),但对于数组,我会使用 find 找到它们,然后从该条目中获取信息:

function personScore(personId) {
  const entry = startingArray.find(entry => entry.personId === personId);
  if (!entry) {
    return 0;
  }
  let sum = entry.score || 0;
  if (entry.scores) {
    for (const {score} of scores) {
      sum += score;
    }
  }
  return sum;
}

实时复制:

const startingArray = [
  {
    id: 1,
    personId: 1,
    scores: [
      {
        id: 1,
        title: 'Google',
        score: 12
      },
      {
        id: 2,
        title: 'Bing',
        score: 23
      },
      {
        id: 3,
        title: 'Facebook',
        score: 34
      }
    ],
    score: null
  },
  {
    id: 2,
    personId: 1,
    scores: null,
    score: 123
  },
  {
    id: 3,
    personId: 2,
    scores: [
      {
        id: 4,
        title: 'Google',
        score: 7
      },
      {
        id: 5,
        title: 'Bing',
        score: 32
      },
      {
        id: 6,
        title: 'Facebook',
        score: 9
      }
    ],
    score: null
  },
  {
    id: 4,
    personId: 3,
    scores: null,
    score: 106
  },
  {
    id: 5,
    personId: 3,
    scores: [
      {
        id: 7,
        title: 'Google',
        score: 6
      },
      {
        id: 8,
        title: 'Bing',
        score: 4
      },
      {
        id: 9,
        title: 'Facebook',
        score: 3
      }
    ],
    score: 5
  }
]
function personScore(personId) {
  const entry = startingArray.find(entry => entry.personId === personId);
  if (!entry) {
    return 0;
  }
  let sum = entry.score || 0;
  if (entry.scores) {
    for (const {score} of scores) {
      sum += score;
    }
  }
  return sum;
}
console.log(personScore(1));

关于javascript - 如何从基于对象数组内部的对象数组返回值的总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56644319/

相关文章:

algorithm - 最小长度 L 的最大连续子序列和

c++ - 将数组大小减少到 1 的最小成本

Java:可以访问由字符串连接创建的临时对象吗?

javascript - 可以在不使用 `function` 关键字的情况下在对象初始值设定项中定义方法吗?

java - 类型中的方法不适用于参数

javascript - Scrollspy 目录不跟随滚动

javascript - 使用 JavaScript 隐藏 H1 元素

使用 appendchild 时,Javascript childNodes 找不到 div 的所有子节点

javascript - 我的提交功能以 Bad Gateway 502 响应

LINQ:实体字符串字段包含任何字符串数组