前段
A氏「数字が入っているリストがあって、そこから数字の出現回数を調べたいんですけど、連想配列使わない方法ってないですか?」
私 「連想配列じゃダメなのですか?」
A氏「いまいち連想配列が分からないので、可能なら避けて通りたい…」
私 「(他の方法かぁ。ん? でも、これは連想配列を理解するにはいい題材なのでは? 避けて通らない方が!)」
その時に説明した内容を資料にまとめることになりました。
配列と連想配列
ともあれ、この記事をご覧の方の中には配列と連想配列の違いから、という方もいると思うので簡単に説明。
配列は0から始まる数字(インデックス)を指定して作業を行う。
const list: string[] = [
"れもん",
"みかん",
"りんご"
];
console.log(list[0]); // れもん
console.log(list[1]); // みかん
console.log(list[2]); // りんご
連想配列は数字(インデックス)ではなく文字列を指定して作業を行う。
const map: {[key:string]:string} = {
"lemon":"れもん",
"orange":"みかん",
"apple":"りんご"
};
console.log(map["lemon"]); // れもん
console.log(map["orange"]); // みかん
console.log(map["apple"]); // りんご
ストーリー
買い物にいったお母さんが果物をたくさん買って帰ってきました。
スーパーの袋に手を突っ込み、無造作に机の上に並べます。
const fruitList: string[] = [
"れもん",
"みかん",
"りんご",
"みかん",
"りんご",
"れもん",
"みかん",
"りんご",
"みかん",
"みかん",
"ぶどう"
];
そこに子供がやってきました。
子供「1番目の果物は"れもん"だね」
// 1番目(先頭)の要素にアクセスするための数字は0です。
console.log(fruitList[0]); // れもん
母親「そうね。それじゃあ、まず、各果物をまとめましょう」
// 連想配列
const note: { [key: string]: number } = {};
// フルーツリストの数だけ繰り返す
for ( let i = 0; i < fruitList.length; i++ ) {
// フルーツ(の名前)取得
const fruit = fruitList[ i ];
// 連想配列に登録されているかどうか
if ( note[ fruit ] == null ) {
// 連想配列に登録されていなかったら1を設定
note[ fruit ] = 1;
continue;
}
// 連想配列に登録されていたら、登録内容をインクリメント
note[ fruit ] = note[ fruit ] + 1;
}
子供「訳が分からないよ」
母親「順番に見ていけば分かるわ」
子供「がんばる」
母親「最初のフルーツ(fruitList[0]
)は"れもん"だったわね。note
には"れもん"というタイトルをつけたメモを貼り付けて、そこに「正」の字でカウントしましょうか。"れもん"が1つ」
母親「次のフルーツ(fruitList[1]
)は"みかん"。note
に"みかん"はないから、またメモを貼り付けるわね」
母親「次のフルーツ(fruitList[2]
)は"りんご"。これもnote
にメモを貼り付ける」
母親「次のフルーツ(fruitList[3]
)は"みかん"。あ、note
に"みかん"があるじゃないの。それなら「正」の字の縦線を書くわね。これを繰り返して…」
母親「ふぅ、全部で11個もフルーツを買っていたのね。でも、これで分類が終わったわ」
子供「一番たくさんあったのは、どれかな?」
母親「まず、タイトルを抜き出して並べてみましょうか」
const memoTitleList = Object.keys( note );
母親「これを順番に比較していくわ。例えば、"れもん"と"みかん"ならどちらが大きいかしら?」
子供「"みかん"!」
母親「正解よ。それじゃ、その繰り返しで、一番たくさん入っていたのは何か調べましょう」
子供「がんばる」
// 初期値
let maxNum = 0;
let maxNumFruit = "";
// 連想配列noteの、key値の配列を取得
const memoTitleList = Object.keys( note );
// memoTitleListの数だけ繰り返す
for ( let i = 0; i < memoTitleList.length; i++ ) {
const memoTitle = memoTitleList[ i ];
// 連想配列noteにkey値であるmemoTitle(果物の名前)を与えて、value(正の字の数)を得る
const fruitCount = note[ memoTitle ];
// 保持しておいた最大数と比較
if ( maxNum > fruitCount ) {
// value(正の字で数えた数)が最大値より小さい場合はcontinue
continue;
}
// 最大数とその果物名を保持
maxNum = fruitCount;
maxNumFruit = memoTitle;
}
console.log( maxNum ); // 5
console.log( maxNumFruit ); // みかん
子供「一番たくさん買ったのは、"みかん"だ!」
母親「うちの子、天才(涙)」
コード
ストーリーで使ったもの
const fruitList: string[] = [
"れもん",
"みかん",
"りんご",
"みかん",
"りんご",
"れもん",
"みかん",
"りんご",
"みかん",
"みかん",
"ぶどう"
];
// 連想配列
const note: { [key: string]: number } = {};
// フルーツリストの数だけ繰り返す
for ( let i = 0; i < fruitList.length; i++ ) {
// フルーツ(の名前)取得
const fruit = fruitList[ i ];
// 連想配列に登録されているかどうか
if ( note[ fruit ] == null ) {
// 連想配列に登録されていなかったら1を設定
note[ fruit ] = 1;
continue;
}
// 連想配列に登録されていたら、登録内容をインクリメント
note[ fruit ] = note[ fruit ] + 1;
}
// 初期値
let maxNum = 0;
let maxNumFruit = "";
// 連想配列noteの、key値の配列を取得
const memoTitleList = Object.keys( note );
// memoTitleListの数だけ繰り返す
for ( let i = 0; i < memoTitleList.length; i++ ) {
const memoTitle = memoTitleList[ i ];
// 連想配列noteにkey値であるmemoTitle(果物の名前)を与えて、value(正の字の数)を得る
const fruitCount = note[ memoTitle ];
// 保持しておいた最大数と比較
if ( maxNum > fruitCount ) {
// value(正の字で数えた数)が最大値より小さい場合はcontinue
continue;
}
// 最大数とその果物名を保持
maxNum = fruitCount;
maxNumFruit = memoTitle;
}
console.log( maxNum ); // 5
console.log( maxNumFruit ); // みかん
整理版
const fruitList: string[] = [
"れもん",
"みかん",
"りんご",
"みかん",
"りんご",
"れもん",
"みかん",
"りんご",
"みかん",
"みかん",
"ぶどう"
];
const note: { [key: string]: number } = {};
let maxNum = 0;
let maxNumFruit = "";
const len = fruitList.length;
for ( let i = 0; i < len; i++ ) {
const fruit = fruitList[ i ];
let fruitCount = note[ fruit ] == null ? 1 : note[ fruit ] + 1;
note[ fruit ] = fruitCount;
if ( maxNum > fruitCount ) {
continue;
}
maxNum = fruitCount;
maxNumFruit = fruit;
}
console.log( maxNum ); // 5
console.log( maxNumFruit ); // みかん
補足
-
Object.keys
でとれる順番は、画像のように「れもん-みかん-りんご-ぶどう」とは限りません。 - コードはTypeScriptで書いてますが、型部分を消せばjsとしても使える、と思います。(ただし、検証はしていない)
素材
いらすとやさんの素材を使わせていただきました。