質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.35%

for文での上手な短縮の仕方がわかりません。

解決済

回答 6

投稿

  • 評価
  • クリップ 0
  • VIEW 1,674

score 356

 前提・実現したいこと

javascriptで乱数Pk(xk,yk)*3点(k=0~2)を発生させ三角形とし、
ベクトル計算から重心を求めるものを想定しています。(拡張して三角形のその他5心も求めるものも別途書きました。そちらについては、今後再質問させていただくかもしれません。)

プログラムはできているのですが、素人目にも増長になりすぎて、短縮している過程ですが、
うまい方法が思いつきません。

具体的には該当ソースコードの以下の部分の省略に手間取っております。
var x0=parseFloat(document.getElementById('x0').value);
var x1=parseFloat(document.getElementById('x1').value);
var x2=parseFloat(document.getElementById('x2').value);
var y0=parseFloat(document.getElementById('y0').value);
var y1=parseFloat(document.getElementById('y1').value);
var y2=parseFloat(document.getElementById('y2').value);
この部分を短くfor文を使って回したいです。

 発生している問題・エラーメッセージ

 該当のソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<style></style>
</head>
<body>

<script>
    function atk(){

var fm = document.getElementById('fm');
fm.innerHTML="";

var arr=[];

for(k = 0; k < 3; k++){
  var inputX = document.createElement('input');
  inputX.type = 'number';
  inputX.size = 10;
  inputX.id = `x${k}`;
  inputX.placeholder = `x${k}`;

  var inputY = document.createElement('input');
  inputY.type = 'number';
  inputY.size = 10;
  inputY.id = `y${k}`;
  inputY.placeholder = `y${k}`;
  inputY.value = `y${k}`;

  var br = document.createElement('br');

  var before = document.createTextNode(`p${k}(`);
  var comma = document.createTextNode(',');
  var after = document.createTextNode(')');

  fm.append(before);
  fm.append(inputX);
  fm.append(comma);
  fm.append(inputY);
  fm.append(after);
  fm.append(br);

  var p=(Math.random()*1000);
  var q=(Math.random()*1000);

  document.getElementById(`x${k}`).value=p;
  document.getElementById(`y${k}`).value=q; 
  arr.push({x:p,y:q});
}

var x0=parseFloat(document.getElementById('x0').value);
var x1=parseFloat(document.getElementById('x1').value);
var x2=parseFloat(document.getElementById('x2').value);
var y0=parseFloat(document.getElementById('y0').value);
var y1=parseFloat(document.getElementById('y1').value);
var y2=parseFloat(document.getElementById('y2').value);

 //g
const g=[];
const gx=(x0+x1+x2)/3;
const gy=(y0+y1+y2)/3;
g.push(gx);
g.push(gy);
alert(g);
}

</script>

<form id="fm"></form>
<input type="button" id="Atk" onclick="atk()" value="solve">


</body>
</html>

 試したこと

for(k…){}の中に
x[k]=parseFloat(document.getElementById('y${k}').value);
とした所、
今まで正常に表示されていたp1,p2ポイントのxy座標のinputタグまで表示されなくなってしまいました。
そこで、for(m…)のループをkの後に追加しkをmと置き換えて回してみましたが、
今度はxy座標の取得に失敗してしまいました。
kのループの中ではp,q座標配列取得が最終項しか何故かできず、
今後のその他5心を求めるために必要な情報として配列として残すのに失敗してしまいました。

わかりにくい質問で申し訳ありませんが、何卒よろしくお願い申し上げます。

 補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

+2

 Don't repeat yourself (DRY)

基本的にはDRYの原則に従えば、コードは冗長ではなくなります。

同じコードをリピートしない為には、

  • 同じ演算結果を変数にキャッシュする
  • 引数だけが違う同じ動作は、配列+繰り返し構文の複合を使う
  • 同じコードを関数にまとめる

 コードを短縮化

関数と繰り返し構文は二者択一の関係にあります。
下記は、繰り返し構文で解決したコードです。

<form id="fm"></form>
<input type="button" id="Atk" onclick="atk(3)" value="solve" />

<script>
'use strcit';
function atk (length) {
  const map = new Map([['x', []], ['y', []]]), df = document.createDocumentFragment();

  for (var i = 0; i < length; i++) {
    df.appendChild(document.createTextNode('p' + i + '('));

    for (let [key, array] of map) {
      const input = document.createElement('input'), name = key + i, value = Math.random() * 1000;

      input.type = 'number';
      input.size = 10;
      input.name = name;
      input.placeholder = name;
      input.value = value;

      df.appendChild(input);
      df.appendChild(document.createTextNode(','));
      array.push(value);
    }

    df.lastChild.data = ')';
    df.appendChild(document.createElement('br'));
  }

  const form = document.getElementById('fm'), results = [];

  form.innerHTML = '';
  form.appendChild(df);

  for (let array of map.values()) {
    let sum = 0;

    for (let value of array) {
      sum += value;
    }

    results.push(sum / array.length);
  }

  alert(JSON.stringify(results));
}
</script>

length を可変に出来るのが、配列,new Mapのメリットです。
拡張性も視野に入れると、コードの幅が広がると思います。


(2018/09/24 10:35追記)
input要素挿入時に合計値算出をする形に改善したコード。

'use strcit';
function atk (length) {
  const results = new Map([['x', [0, 0]], ['y', [0, 0]]]), df = document.createDocumentFragment();

  for (var i = 0; i < length; i++) {
    df.appendChild(document.createTextNode('p' + i + '('));

    for (let [key, entry] of results) {
      const input = document.createElement('input'), name = key + i, value = Math.random() * 1000;

      input.type = 'number';
      input.size = 10;
      input.name = name;
      input.placeholder = name;
      input.value = value;

      df.appendChild(input);
      df.appendChild(document.createTextNode(','));
      entry[0] += value;
      ++entry[1];
    }

    df.lastChild.data = ')';
    df.appendChild(document.createElement('br'));
  }

  const form = document.getElementById('fm');

  form.innerHTML = '';
  form.appendChild(df);

  alert([...results.values()].map(entry => entry[0] / entry[1]));
}

 クラス化

コード短縮化が命題でしたので、短縮のみの視点で回答しましたが、私が提案したコードはループ回数を減らす為に複数の役割を同一コード上で実行しており、それがコードの可読性を下げている面はあると思います。
パフォーマンス寄りにチューニングすれば、「密結合」が進み、保守性にチューニングすれば、「疎結合」が進みます。
このバランスは人それぞれですが、「座標」の視点で暮らす化したコード例を書いておきます。

基本的な方針は、次の3つの処理を分化する事にあります。

  • データを生成する (new Coordinatenew CoordinateList)
  • データを使って演算する (CoordinateList#getCenter())
  • データを出力する (DOMノードの挿入)

特にDOMノード系は処理を分けた方が良いと思います。後は、論理エラーをクラス内で排除します。

<form id="fm"></form>
<input type="button" id="atk" value="solve" form="fm" />

<script src="coordinate-list-0.1.0.js"></script>
<script>
'use strcit';
(function () {
  function generateDf (coordinateList) {
    const df = document.createDocumentFragment();

    for (let i = 0, entries = coordinateList.entries(), length = entries.length; i < length; i++) {
      df.appendChild(document.createTextNode('p' + i + '('));

      for (let [key, entry] of entries[i]) {
        const input = document.createElement('input'), name = key + i, value = Math.random() * 1000;

        input.type = 'number';
        input.size = 10;
        input.name = name;
        input.placeholder = name;
        input.value = value;

        df.appendChild(input);
        df.appendChild(document.createTextNode(','));
      }

      df.lastChild.data = ')';
      df.appendChild(document.createElement('br'));
    }

    return df;
  }

  function createRandomCoordinateList (dimensionList, length) {
    const coordinateList = [];

    for (let i = 0; i < length; ++i) {
      const coordinate = [];

      for (let dimension of dimensionList) {
        coordinate.push([dimension, Math.random() * 1000]);
      }

      coordinateList.push(coordinate);
    }

    return new CoordinateList(coordinateList);
  }

  function handleClick (event) {
    const coordinateList = createRandomCoordinateList(this.dimensionList, this.length), form = event.target.form;

    form.innerHTML = '';
    form.appendChild(generateDf(coordinateList));

    console.log(coordinateList.getCenter());
  }

  function main () {
    this.document.getElementById('atk').addEventListener('click', {
      handleEvent: handleClick,
      length: 3,
      dimensionList: ['x', 'y']
    }, false);
  }

  main.call(this);
}.call(this));
</script>

Re: hectopascal1013 さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/24 11:36

    ご提示ありがとうございます。
    私が理解できる範囲をだいぶ超えているので、これからじっくりと中身を確認して、身につけていきたいと思います。
    大分無駄が多かった点を省いてくださり感謝します。
    2つに方向性を分けて書いていただいたのもありがたかったです。
    また理解しつつお聞きしたい点も出てくると思いますので引き続きよろしくお願い申し上げます。

    キャンセル

  • 2018/09/24 23:26

    一応、 クラス化したコードを追記しておきました。
    最も、汎用性を重視したので、多少コードは長いです。
    - 論理エラーを検出できる
    - 三角形だけでなく、N角形を定義出来る
    - x,y座標だけでなく、z座標も定義出来る
    - iterable なオブジェクトを引数にとれる

    キャンセル

  • 2018/09/27 08:14

    沢山書いて頂いてたのに、お礼が遅くなりまして申し訳ありません。
    Firefoxの方から更新してコメントできてたと思ってましたができてませんでした。。;;

    reduceやmapもまだ理解してない初めて半週の私には内容てんこ盛りで、まだまだ理解していない部分もありますが、一通り試させていただいて、おしゃって頂いてる事の1割もわかっているかは怪しいですが、これからじっくり参考にさせていただきます!
    本当にありがとうございました。

    キャンセル

+2

こんにちは。

この回答で説明する考え方、コード追加、修正によって作成したコードを、以下のURL

動作確認用のサンプル:  https://jsfiddle.net/jun68ykt/g69zsfha/2/

に上げましたのでお試しください。(※ランダムな座標を発生させる、[generate]ボタンを追加しています)

ご質問に挙げられているコードを、私がリファクタするとしたら、

  • ロジックとビュー(UI)をできるだけ分離する。

ことを目指します。このご質問でロジックとは主に

  • 乱数による座標の生成
  • 重心の計算

の2点で、ビューの役割は主に以下の2点です。

  • 生成された複数の座標を対応する<input> の value 属性に反映させる。
  • ボタンがクリックされたときに、重心計算を行い結果を表示する。

また、

  • ランダムな座標を持つ複数の点を(まとめて)どこに保存しておくか?

という点もコードを見通しよく保つために重要かなと思いますが、これの解決策として、data-属性を使いました。

上記の指針により、以下のようなコード修正、追加を行いました。

 1. ロジック

 1.1 Pointコンストラクタの追加

xy座標上の点を表す、Pointコンストラクタを追加します。

    const Point = function(x, y) {
      this.x = x;
      this.y = y;
    };

    Point.prototype.toString = function() {
      return `x: ${this.x}, y: ${this.y}`;
    };

 1.2  ランダムな座標を持つ複数の点の生成

生成する点の数を受け取り、その数のPointオブジェクトを持つ配列を返す関数を作ります。座標はご質問と同じく、Math.random() * 1000 でランダムに生成させます。

      // 乱数を使ってランダムな座標を生成
      function generateRandomPoints(numberOfPoints) {
        return [...Array(numberOfPoints)].map(_ =>
          new Point(Math.random() * 1000, Math.random() * 1000)
        );
      }

 1.3  重心の取得

与えられた Pointオブジェクト(あるいは、Pointと同様にxyをプロパティに持つオブジェクト)の配列から、これらの重心となるPointを返す関数を作ります。

      // 重心の取得
      function getCenterOfGravity(points) {
        if (!points || !points.length)
          return null;

        return new Point(
          points.reduce((sum,p) => sum + p.x, 0) / points.length,
          points.reduce((sum,p) => sum + p.y, 0) / points.length
        );
      }

 2. ビュー

 2.1  3点の座標を表示するHTMLは<form>の中に直接書く。

以下のように <form>の中に直接書き、かつ、各 <input>に "x"または"y" のclass属性を追加し、次の 2.2 で使用します。

  <form id="fm">
    p0(
    <input type="number" size="10" id="x0" class="x" placeholder="x0">,
    <input type="number" size="10" id="y0" class="y" placeholder="y0">)<br>
    p1(
    <input type="number" size="10" id="x1" class="x" placeholder="x1">,
    <input type="number" size="10" id="y1" class="y" placeholder="y1">)<br>
    p2(
    <input type="number" size="10" id="x2" class="x" placeholder="x2">,
    <input type="number" size="10" id="y2" class="y" placeholder="y2">)<br>
  </form>

五角形の重心を求める場合は、上記と同様に  p3、 p4 に相当するHTMLを追加します。 

 2.2 与えられた複数のPointの座標をHTMLに反映

行うことは以下の2点です。

  • 指定されたPointオブジェクトの配列の各要素の座標を、対応する <input>の value 属性に設定
  • 指定されたPointオブジェクトの配列をJSON化して、<form>の data-points 属性に設定
      // 与えられた複数のPointの座標をHTMLに反映
      function renderPoints(points) {

        // 対応する <input>の valueに設定
        ['x', 'y'].forEach(function(axis) {
          const inputs = document.getElementsByClassName(axis);
          for (let i=0; i < inputs.length && i < points.length; i ++ )
            inputs[i].value = points[i][axis];
        });

        // <form> のdata-points属性にpointsをJSONにした文字列を設定
        const form = document.getElementById('fm');
        form.dataset.points = JSON.stringify(points);
      }

 2.3 ランダム座標を生成するトリガーになるボタンとクリックハンドラ設定

HTMLに以下のようなボタンを追加します。

<input type="button" id="Generate" value="generate">

上記のボタンをクリックすると、ランダムな座標が生成され、HTMLに反映されるようにします。

const NUMBER_OF_POINTS = 3;
      // generateボタンにclickハンドラを設定
      document.getElementById('Generate').addEventListener('click',
        function() {
          const randomPoints = generateRandomPoints(NUMBER_OF_POINTS);
          renderPoints(randomPoints);
        }
      );

 2.4 solveボタンにclickハンドラを設定

solveボタンがクリックされたときに重心が計算され、表示されるようにします。重心を計算する対象のPointオブジェクトの配列は、<form>の data-points 属性にJSONで入っている想定なので取り出して、これを重心を取得する関数に渡します。

      // solveボタンにclickハンドラを設定
      document.getElementById('Atk').addEventListener('click',
        function() {
          const form = document.getElementById('fm');
          if (form.dataset.points) {
            const points = JSON.parse(form.dataset.points);
            const g = getCenterOfGravity(points);
            alert(g);
          }
        }
      );

ご質問に

具体的には該当ソースコードの以下の部分の省略に手間取っております。
var x0=parseFloat(document.getElementById('x0').value);
var x1=parseFloat(document.getElementById('x1').value);
var x2=parseFloat(document.getElementById('x2').value);
var y0=parseFloat(document.getElementById('y0').value);
var y1=parseFloat(document.getElementById('y1').value);
var y2=parseFloat(document.getElementById('y2').value);

とありました。上記の6行では、HTMLに反映された各点の座標を取得していますが、私の回答のコードで、これと同じ働きをしているのは以下の行です。

    const form = document.getElementById('fm');
    if (form.dataset.points) {
      const points = JSON.parse(form.dataset.points);

以上、参考になりましたら幸いです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/24 15:07

    ご指導ありがとうございます。illustratorでのjavascript表記を念頭にしてますので、JSONなどが使えるかは定かではないですが、純粋なjavascriptの勉強としてご指導感謝します。こういった方法は、一人では思いつかないものですので、大変にありがたいです。

    キャンセル

  • 2018/09/24 18:07

    Generateボタンとsolveボタンを分けられた理由ってなんでしょうか?(素朴な疑問です。)
    あと、質問内容が悪かったようで訂正します。
    三角形の5心(重心、内心、外心、垂心、傍心)についてのプログラムですので、
    今の所5角形拡張は考えておりません。すいません伝わりづらいようでしたので、訂正します。

    配列流用は内心以後の5心でも座標を使えるということでした。
    ともあれ、自分で書いたものをできるだけ簡潔にしたいという思いもあり、
    練習がてら、皆様のご意見ご指導を仰いでますので、ご指摘いただいた点は視点が広がりますので、何かと助かっております。引き続きよろしくお願いいたします。

    キャンセル

  • 2018/09/24 19:00 編集

    > Generateボタンとsolveボタンを分けられた理由ってなんでしょうか?(素朴な疑問です。)

    ご質問ありがとうございます。私の回答では

    ・ランダムな座標を持った点の配列を生成すること



    ・重心を求めること

    とを、それぞれ個別の関数で行うようにし、それぞれの関数名を見れば何をする関数かがすぐ分かるようなコードにしましたが、これは「私ならこう書くだろうな」という個人的な考えに過ぎません。

    > Generateボタンとsolveボタンを分けられた

    のは、「ランダムな座標の点の生成」と「重心の計算」とを分離したことを、UIからも明確に視認できるようにするためでした。ですので「Generateボタンとsolveボタンとを分けるべき」と主張したいわけではありませんし、質問者様が
    「solveボタンのクリックだけで、3点の生成から重心の計算まですべてが行われることが望ましい」
    ということであれば、そのような1個のボタンだけのUIにされましても全く問題はないと思います。

    キャンセル

  • 2018/09/24 20:15

    ご回答ありがとう御座います。
    UIを意識しているということですね?わかりました。

    一応、私の最初の質問(今回のものではなくて、本当に最初期の質問です。)に立ち返りますと、
    Adobe Illustrator上でjavascriptを動かすということを念頭においておりまして、
    その点では、UIに対する独自仕様が強いものとなっているようですので、また別途勉強したいと考えております。

    今回の作例では、ですから、あまりその辺は意図せず、1Functionでできるだけ済ませられるように考えておりました。
    前提の段を飛ばしてしまいましたので、ソコは私のミスです。

    ただ、純粋なjavascriptの勉強としては、UIも考えて仕様を分けるというのは、仰る通り理想的で、今までの私の考えにないことでしたので、大変為になりました。
    ボタンを分けてもエラーを起こさず利用できるという点では、例えば乱数生成時ではなくて、正三角形時や二等辺三角形時など、特定の値を後から埋め込むタイプなどにも応用が効きそうで、とても役に立つ流れになっています。ありがとうございます。

    キャンセル

checkベストアンサー

+1

私が作るならこんな感じの設計にしますね。

cconst indexes = [0, 1, 2];
const dimensions = ['x', 'y'];

// 中身全体を毎回生成する意味はないので、コンテンツ読み込み完了後一度だけHTML更新。
// 初回起動時に要素を作るため、微妙に挙動が変わっていますが……
document.addEventListener('DOMContentLoaded', ()=>{
  function createInput(dimension, index){
    return Object.assign(
      document.createElement('input'),
      {
        type: 'number',
        sixe: 10,
        id: `${dimension}${index}`,
        placeholder: `${dimension}${index}`,
        value: Math.random()*1000
      }
    );
  }
  indexes.forEach(i=>{
    const inputs = dimensions.map(d=>createInput(d, i));
    [
      document.createTextNode(`p${i}(`),
      inputs[0],
      document.createTextNode(','),
      inputs[1],
      document.createTextNode(')'),
      document.createElement('br')
    ].forEach(el=>document.getElementById('fm').append(el));
  });
});
function atk(){
  // 値を取得
  const val = dimensions.map(d=>{
    return indexes
      .map(i=>document.getElementById(`${d}${i}`).value)
      .map(v=>parseFloat(v));
  });
  // 重心を計算
  const g = val.map(v=>
    v.reduce((prev, crnt)=>prev + crnt) / v.length
  );
  alert(g);
}

若干、挙動を私好みに変えてしまいましたが。

56行くらい→ 43行くらいと、行数はあまり短縮していませんが、コードの見通しが良くなったと思いませんか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/24 07:33

    >私が作るならこんな感じの設計にしますね。
    これは素晴らしい。私が気づいていなかったことまでご指摘いただきありがとうございます。
    一人でやっているため、なかなか指摘を受けることもなかったので、こういう視点の組み方は非常に勉強になります。まだまだ、舐める程度で、理解には追いつかない点も多いですが、mapやredeceもうまく使えるようになりたいです。

    キャンセル

+1

function atk() {
  var fm = document.getElementById('fm');
  fm.innerHTML = "";

  var arr = [], points = [];

  for (k = 0; k < 3; k++) {
    var inputX = document.createElement('input');
    inputX.type = 'number';
    inputX.size = 10;
    inputX.id = `x${k}`;
    inputX.placeholder = `x${k}`;

    var inputY = document.createElement('input');
    inputY.type = 'number';
    inputY.size = 10;
    inputY.id = `y${k}`;
    inputY.placeholder = `y${k}`;
    inputY.value = `y${k}`;

    var br = document.createElement('br');

    var before = document.createTextNode(`p${k}(`);
    var comma = document.createTextNode(',');
    var after = document.createTextNode(')');

    fm.append(before);
    fm.append(inputX);
    fm.append(comma);
    fm.append(inputY);
    fm.append(after);
    fm.append(br);

    var p = (Math.random() * 1000);
    var q = (Math.random() * 1000);

    document.getElementById(`x${k}`).value=p;
    document.getElementById(`y${k}`).value=q; 
    arr.push({x:p,y:q});

    points.push({x:parseFloat(document.getElementById('x' + k).value), y:parseFloat(document.getElementById('y' + k).value)});
  }

   //g
  const g = [];
  const gx = (points[0].x + points[1].x + points[2].x) / 3;
  const gy = (points[0].y + points[1].y + points[2].y) / 3;
  g.push(gx);
  g.push(gy);
  alert(g);
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/24 07:34

    pushの時点でparseFloat使えるんですね。目からウロコです。ありがとうございます。
    皆さん書き方が簡潔で美しいので、それを真似できるようにがんばります。

    キャンセル

+1

変数が配列になっても良ければこんな感じでどうでしょう??
ご指定の箇所をfor文で短くしたバージョンです|ー゚)

let x = [];
let y = [];

for(let i = 0; i < 3; i++){
  x[i] = parseFloat(document.getElementById('x' + i).value);
  y[i] = parseFloat(document.getElementById('y' + i).value);
}
 //g
const g = [];
const gx = (x[0]+x[1]+x[2])/3;
const gy = (y[0]+y[1]+y[2])/3;
g.push(gx);
g.push(gy);
alert(g);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/24 07:29

    haru_hime様ありがとうございます。
    多分私がやりたかった意図を、一番くんでくださったお答えなのではないかと思います。
    xとyで配列を分けるというのは初心者にもわかりやすいやり方ですね。
    一度にまとめて書こうとすると混乱もするし、間違いも犯しやすいので、練習に取り入れたいと思います。

    キャンセル

  • 2018/09/24 11:30

    すいません。追加質問です。
    let x = [];
    let y = [];
    をつけ忘れたパターンは自分で試しましたが、alertでgを出すことに失敗しました。
    コレをつけないことで表示されなくなってしまう理由ってなんでしょうか?

    キャンセル

  • 2018/09/26 22:40

    let x = [];
    let y = [];
    が無い時にalertが作動しないということでしょうか?

    配列は宣言しなかった場合
    x[0] = 10;
    は、
    let x;
    x[0] = 10
    みたいな事をした感じになるんではないかなと勝手に予想してやってます。

    もちろんエラーが出ますのでそれ以降の処理は中断されます。
    for分の直前や、for文の中の先頭に
    console.log("ここまで動いた:目印");
    を追加して動かしてみるとどこで止まったのかなどが目に見えるので理解しやすいかと思います。
    ちなみに、ボタンを押して表示が更新されるのはボタンを押すたびにエラーが出る
    x[i] = parseFloat(document.getElementById('x' + i).value);
    の行まで実行されるからです。

    変数の宣言については、あまり深く考えた事が無かった(←趣味とはいえ反省してますw)ので詳しい方にバトンパスです|ー゚)

    クロージャ スコープ スコープチェーンなどの検索用語で色々出てきそうなので勉強してきます!
    良い機会感謝です(n*´ω`*n)

    キャンセル

  • 2018/09/27 08:17

    >クロージャ スコープ スコープチェーンなど

    私も勉強します。
    console.logやalertの確認はするようにします。
    変数宣言については他の質問で同じようにご指摘頂いた事でまた一歩、少しですが理解が深まりました。
    私の方でまだまだ基礎も確立していない段階ですので、おかしな質問だったらすいません。
    ご回答ありがとうございます。

    キャンセル

+1

5角形をどうやって3角形に分割しようとしているのかわかりませんが、
arrに3角形の頂点が入っているので、それを使ってはどうでしょうか。

const gx = arr.reduce((a, c)=> a + c.x, 0) / 3;
const gy = arr.reduce((a, c)=> a + c.y, 0) / 3;

Array::reduce


余談ですが、現状のロジックを私であれば以下のように作ります。
もし、参考になる部分があればどうぞ。

function atk(){
  const createInputElement = (id, value) =>{
    const input = document.createElement('input');
    input.type = 'number';
    input.size = 10;
    input.id = id;
    input.placeholder = id;
    input.setAttribute('value', value);
    return input;
  } 

  const fm = document.getElementById('fm');
  fm.innerHTML="";

  const arr = [];
  for(let k=0; k<3; k++) {
    const x = (Math.random()*1000);
    const y = (Math.random()*1000);    
    arr.push({x, y});

    const inputX = createInputElement(`x${k}`, x);
    const inputY = createInputElement(`y${k}`, y);

    const div = document.createElement('div');
    div.innerHTML = `p${k}(${inputX.outerHTML},${inputY.outerHTML})`;
    fm.append(div);
  }

  const gx = arr.reduce((a, c)=> a + c.x, 0) / 3;
  const gy = arr.reduce((a, c)=> a + c.y, 0) / 3;
  const g = [gx, gy]
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/24 07:27

    お早いお返事ありがとうございます。返事遅くなってすいません。
    なるほど〜。すでにあるarrを利用するにはreduceを使うのですか。
    超がつく初心者の私は挙動が思い通りにならないため使用を敬遠してましたが、
    こうしてみると簡潔に書けるためにイイですね。勉強します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る