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

时间:2019-06-18 07:56:35

标签: javascript arrays object ecmascript-6

我有以下示例对象数组,该数组中的每个对象都包含一个image classificationidpersonId,最后是scores。在某些对象中,scorescores或包含其他对象数组,它们是得分。在其他对象中,null可以包含一个值而不是score。最后,在某些情况下对象可能同时包含nullscores

score

我可以过滤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) map为该人返回reduce项的值:

score

我在努力挣扎的地方是能够对startingArray.filter(item => item.personId === personId).map(item => item.score).reduce((a, b) => a + b, 0) 数组中与某人相对应的score个项目求和。

最终,我所追求的是能够打电话给scores并返回人1的总分(即69),或者打电话给personScores(1)并返回124(即106 + 13 + 5)。

4 个答案:

答案 0 :(得分:4)

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

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

这是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),但是对于数组,我将使用{{1} }找到它们,然后只需从该条目中获取信息:

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

答案 1 :(得分:1)

您可以使用reduce来获得总和,或者如果我们有一个分数数组,可以再次使用reduce,或者简单地添加在score处的值

function getPersonScore(arr, id) {
  const filtered = id ? arr.filter(e => e.personId === id) : arr;
  return filtered.reduce((a, b) => {
    if (Array.isArray(b.scores)) a += getPersonScore(b.scores);
    return a + (b.score || 0);
  }, 0);
}


console.log(getPersonScore(startingArray, 1));
<script>
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
  }
];
</script>

答案 2 :(得分:0)

const personScores = (id, arr) => {
  // error catching
  if (!Array.isArray(arr)) {
    throw new Error('Input array is not an array');
  }
  if (id >= arr.length) {
    throw new Error(`Id ${id} out of array range (length ${arr.length})`);
  }
  if (!('scores' in arr[id])) {
    throw new Error(`scores key missing in input array`);
  }
  if (!Array.isArray(arr[id].scores)) {
    throw new Error(`Scores of input id ${id} not an array`);
  }

  // iterate scores array of startingArray[id], defaultValue of sum is 0
  return arr[id].scores.reduce((sum, scoreObj) => {
    if ('score' in scoreObj && !isNaN(parseInt(scoreObj.score, 10))) {
      sum += parseInt(scoreObj.score, 10);
    }
    return sum;
  }, 0); // defaultValue of the reducer
};

答案 3 :(得分:0)

首先find您想要的人,然后使用reduce添加他们的scores,最后将其添加到他们的score

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

const personScores = id => {
  let { scores, score } = startingArray.find(({ personId }) => personId);
  let finalScore = 0;
  if (score && score.length) finalScore += (Array.isArray(score) ? score.reduce((a, { score }) => a + score, 0) : score);
  if (scores && scores.length) finalScore += (Array.isArray(scores) ? scores.reduce((a, { score }) => a + score, 0) : scores);
  return finalScore;
};

console.log(personScores(1));
console.log(personScores(3));

(上面的代码检查scorescores两者是否为数组,并相应地执行适当的逻辑)