1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】配列の合計 / 平均 / 中央値を求めるには?

Last updated at Posted at 2024-12-21

合計

コードはこちらです。

/**
 * 配列の合計を求める関数
 * @param {number[]} array 
 * @returns {number} 合計
 */
function sum(array) {
  return array.reduce((acc, cur) => acc + cur, 0)
}
呼び出し例
sum([3, 6]) // 9
sum([1, 3, 5, 2]) // 11

このコードでは、配列のreduceメソッドを用いて合計を計算しています。

reduceとは

配列のreduceは、配列の要素を縮小するメソッドです。

縮小には指定したコールバック関数が使われます。
コールバックは各要素ごとに順番に実行され、返した値が次のループに使われます。
以下の引数で呼び出されます。

  1. accumulator: 前回のコールバック関数が返した値
  2. currentValue: 現在のループの要素
  3. currentIndex: 現在のループのインデックス
  4. array: 呼び出されている配列そのもの

例えば、コールバック関数でaccmulatorcurrentValueを足し、それを返すようにします。
すると簡単に配列の合計が計算できます。

const array = [1, 3, 5]

const sum = array.reduce((acc, cur) => {
  return acc + cur // 合計を返す
})

sum // 9

初期値

コールバック関数が一番最初に呼び出されるとき、accmulatorは配列の一番最初の要素になります。
そのためcurrentValueは配列の1番目(0ではない)の要素が最初に入ります。

const array = [1, 3, 5]
array.reduce((acc, cur) => { // 1と3が最初に入る
  return acc + cur
})

そして、呼び出された配列の中身が空([])だった場合、reduceはエラーを投げます。

const array = []
array.reduce((acc, cur) => acc + cur) // Error!

今回のsum関数は配列が[]でもエラーではなく0を返したいので、これは問題です。

そこで、第二引数のinitialValueが使えます。
これはaccmulatorの初期値を設定するもので、これを入れると配列が[]でもエラーを投げなくなります。

今回は初期値に数値の0を設定します。

const array = []
array.reduce((acc, cur) => acc + cur, 0) // 0

もちろん、array.lengthをチェックするなどして配列が空であることを確認してもOKです。

function sum(array) {
  if (array.length <= 0) return 0
  return array.reduce((acc, cur) => acc + cur)
}

個人的には初期値を設定したほうがすっきりするので好きです。

function sum(array) {
  return array.reduce((acc, cur) => acc + cur, 0)
}

for...ofの場合

先ほどのコードは、以下のようにfor...of文で書くこともできます。

function sum(array) {
  let result = 0
  for (const num of array) {
    result += num
  }
  return result
}
呼び出し例
sum([3, 6]) // 9
sum([1, 3, 5, 2]) // 11

このコードでは合計をresult変数で管理し、配列の要素を順番に足していっています。
そして計算し終わったらresultを返しています。

平均

コードはこちらです。

/**
 * 配列の平均を求める関数
 * @param {number[]} array 
 * @returns {number} 平均
 */
function average(array) {
  const sum = array.reduce((acc, cur) => acc + cur, 0)
  return sum / array.length
}
呼び出し例
average([3, 5]) // 4
average([5, 8, 10, 2, 16]) // 8.2

求め方

平均は以下の手順で求められます。

  1. 合計(sum)を計算する
  2. sumを要素数(array.length)で割る

average関数は、先ほどと同じ方法で合計を計算し、それをarray.lengthで割ったものを返しています。

中央値

コードはこちらです。

/**
 * 配列の中央値を求める関数
 * @param {number[]} array
 * @returns {number} 中央値
 */
function median(array: number[]) {
  const sorted = array.toSorted((a, b) => a - b)
  const centerIndex = sorted.length / 2

  // 真ん中のインデックスが小数か? = array.lengthが奇数か?
  if (Number.isInteger(centerIndex)) {
    // 偶数 中央に近い2つの数の平均を返す
    const a = sorted[centerIndex - 1]
    const b = sorted[centerIndex]
    return (a + b) / 2
  } else {
    // 奇数: インデックスを切り捨てて返す
    return sorted[Math.floor(centerIndex)]
  };
}

求め方

中央値は以下の手順で求めることができます。

  1. 配列の要素をソートする(sorted
  2. 真ん中のインデックス(sorted.length)が小数かを判定する
  3. 小数の場合: 切り捨てた位置にある値を返す
  4. 整数の場合: 真ん中に近い2つの値の平均を返す

配列の要素をソートする

ソートには配列のtoSortedメソッドを使います。
このメソッドはsortに似ていて、ソートした新しい配列を返します。

array.toSorted((a, b) => a - b)

引数に入れた関数(compareFn)は、どのようにソートするかを示すものです。
ここでのa - bは数値を昇順でソートします。

なお、ここではcompareFnの戻り値が何を示すのかわからなくても大丈夫です。
中央値を求めるにあたって、ソートが昇順でも降順でも結果は変わりません。

toSortedの詳細はMDNをご覧ください。

真ん中のインデックスが小数か判定する

まず、以下のコードでは、この後何度も出てくる真ん中のインデックスに名前をつけています。
これは単純にsorted.length2で割ったものです。

const centerIndex = sorted.length / 2

centerIndexの値は以下のようになります。

  • sorted.lengthが偶数の場合: 整数
  • sorted.lengthが奇数の場合: ~.5という形の小数

また、中央値は数値の数が偶数か奇数かで少し求め方が変わります。

  • 偶数の場合: 真ん中に最も近い2つの数の平均になる
  • 奇数の場合: 真ん中の数になる

このため、currentIndexが小数かどうかを判定し、そこから条件分岐で処理を変える必要があります。

判定方法

数が整数かどうか判定するには、Number.isIntegerメソッドが使えます。

if (Number.isInteger(centerIndex) {
  // 整数の場合
} else {
  // 小数の場合
};

整数の場合

整数の場合=配列の長さが偶数の場合、以下の値を返します。

  1. 中央に近い小さいほうのインデックス(currentIndex - 1)の値を取得する
  2. 中央に近い大きいほうのインデックス(currentIndex)の値を取得する
  3. 1と2の値の平均を返す

コードだとこの部分になります。

const a = sorted[centerIndex - 1]
const b = sorted[centerIndex]
return (a + b) / 2

小数の場合

小数の場合、以下の値を返します。

  1. centerIndex切り捨てる
  2. 1のインデックスの値を返す

コードだとこの部分になります。

return sorted[Math.floor(centerIndex)]

ここで切り捨てている(Math.floorを使っている)理由は、配列のインデックスが0から始まるからです。
例えば、インデックス0 ~ 2の中央は、3 / 2 = 1.5を切り捨てて1になります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?