Sae/note

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

目次

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

    課題ではあらかじめ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でデータを格納できるだと...?!
    早速使ってみよう

    https://twitter.com/terrace_tech/status/1553266531299389440?s=20&t=qfjViXdmzYQ6_coxp2B__Q

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

    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/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));
    

    もりけん塾でJavaScriptを学習をしています!
    もりけん先生のTwitter:https://twitter.com/terrace_tech

    https://kenjimorita.jp/