【もりけん塾】言語チャレンジ@uniqueな要素の配列と、その要素をカウントした配列をつくる

JavaScript

もりけん塾の課題 言語チャレンジ に取り組んでいます!

課題ではあらかじめinputする値とoutputする値が決まっていて、
inputの値を関数の引数として渡し、outputの値を出力するというものです
ここではinputとoutputの値が合っていればクリアとなります
ブログでは課題を解くために考えたことや、様々な書き方を模索することを目的としています。

課題30

ランダムな数字があります。昇順のユニークな要素配列とそのユニーク要素が何回出現したかを表す配列を出力してください。for文で実装すること

input

[2, 2, 5, 2, 2, 2, 4, 5, 5, 9];

output

[[2,4,5,9], [5,1,3,1]]

とりあえず書いてみる

uniqueな値と、それがいくつ出現したかを格納できるようなObjectを作ればいいのでは?
[{uniq: uniq,count: count}...] ←こんな感じ

const input = [2, 2, 5, 2, 2, 2, 4, 5, 5, 9];

const f = (parma) => {
  let arr = [];
  let uniq = [];
  let count = [];
  for (let i = 0; i < parma.length; i++) {
    if (parma.indexOf(parma[i]) === i) {
      arr.push({ uniq: parma[i], count: 1 });
    } else {
      const a = arr.find((d) => d.uniq === parma[i]);
      a.count++;
    }
    arr.sort((a, b) => a.uniq - b.uniq);
  }

  arr.forEach((d) => {
    uniq.push(d.uniq);
    count.push(d.count);
  });

  return [uniq, count];
};

console.log(f(input));

最終的に配列にするための処理(forEachしているところ)がなんか苦しい気がする…

{uniq: count}にしてみる

格納するデータ構造を[{uniq: count},....]のように
keyにuniqueな値、値をカウント数にすれば最終的にObject.Keys or Object.valuesで配列で取り出しやすいのでは…?

const input = [2, 2, 5, 2, 2, 2, 4, 5, 5, 9];

const f = (parma) => {
  let obj = {};
  for (let i = 0; i < parma.length; i++) {
    if (parma.indexOf(parma[i]) === i) {
      obj[parma[i]] = 1;
    } else {
      obj[parma[i]]++;
    }
  }
  const changeToNumbers = () => Object.keys(obj).map((value) => Number(value));
  return [changeToNumbers(), Object.values(obj)];
};

console.log(f(input));

KeyがStringな為、最終的にNumberへ型変換しないとなのが気になるな

Mapを使用してみる

先生のツイートを発見…
MapはkeyをNumberでデータを格納できるだと…?!
早速使ってみよう

const input = [2, 2, 5, 2, 2, 2, 4, 5, 5, 9];

const f = (parma) => {
  const map = new Map();
  const sortedArr = [...parma].sort((a, b) => a - b);
  for (let i = 0; i < sortedArr.length; i++) {
    if (sortedArr.indexOf(sortedArr[i]) === i) {
      map.set(sortedArr[i], 1);
    } else {
      const count = map.get(sortedArr[i]);
      map.set(sortedArr[i], count + 1);
    }
  }
  return [[...map.keys()], [...map.values()]];
};

console.log(f(input));

Map - JavaScript | MDN
Map オブジェクトはキーと値のペアを保持し、キーが最初に挿入された順序を覚えています。キーや値には任意の値(オブジェクトとプリミティブ値)を使用することができます。

それぞれ配列にpushする

filterで対象の値だけの配列([2,2,2,2,2,2])にして、lengthで数を取得することもできるのでは…?

const input = [2, 2, 5, 2, 2, 2, 4, 5, 5, 9];

const f = (parma) => {
  const count = [];
  const uniq = [];
  parma.sort((a, b) => a - b);
  for (let i = 0; i < parma.length; i++) {
    if (parma.indexOf(parma[i]) === i) {
      uniq.push(parma[i]);
      count.push(parma.filter((d) => d === parma[i]).length);
    }
  }
  return [uniq, count];
};

console.log(f(input));
タイトルとURLをコピーしました