teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

17

テキスト修正

2018/08/11 00:42

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -1,16 +1,18 @@
1
1
  こんにちは。
2
+ ご質問に
2
3
 
3
4
  > もっといい感じの書き方があるのではないでしょうか。
4
5
 
5
- いうご質問を 「`if`〜 `else` を使わないで書いてみる」というお題と解釈しての回答になりますが、以下でどうでしょう?
6
+ あります。何もって `いい感じ` のコードとするかは、回答者の私見に委ねられているものと思いますが、私は 「`if`〜 `else` を使わないで書いてみるとどうなりますか?」というお題と解釈したので、それに沿っての回答になります
6
7
 
8
+ [Math.min](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/min) と[Math.max](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/max)を使って、以下でどうでしょう?
9
+
7
10
  ```javascript
8
11
  x = Math.min(COL-1, Math.max(0, x));
9
12
  y = Math.min(ROW-1, Math.max(0, y));
10
13
 
11
14
  ```
12
- ただし、上記はあくまでコードのタイプ量の少なさにこだわった書き方です。
15
+ 上記はあくまでコード量の少なさ、見た目のコードの短さにこだわった書き方です。
13
-
14
16
  参考までに、stackoverflow にも同様の質問(javascriptではないですが。)
15
17
 
16
18
  - [Where can I find the “clamp” function in .NET?](https://stackoverflow.com/questions/2683442/)

16

テキスト修正

2018/08/11 00:42

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -1,11 +1,35 @@
1
1
  こんにちは。
2
- 以下でどうでしょう?
3
2
 
3
+ > もっといい感じの書き方があるのではないでしょうか。
4
+
5
+ というご質問を 「`if`〜 `else` を使わないで書いてみる」というお題と解釈しての回答になりますが、以下でどうでしょう?
6
+
4
7
  ```javascript
5
8
  x = Math.min(COL-1, Math.max(0, x));
6
9
  y = Math.min(ROW-1, Math.max(0, y));
7
10
 
8
11
  ```
12
+ ただし、上記はあくまでコードのタイプ量の少なさにこだわった書き方です。
13
+
14
+ 参考までに、stackoverflow にも同様の質問(javascriptではないですが。)
15
+
16
+ - [Where can I find the “clamp” function in .NET?](https://stackoverflow.com/questions/2683442/)
17
+
18
+ が挙がっていて、こちらの回答の中にも、`Math.Min` と `Math.Max`を使う、以下の回答があります。
19
+
20
+ - [https://stackoverflow.com/a/20443081](https://stackoverflow.com/a/20443081)
21
+
22
+ ですが、上記の回答に対する[このコメント](https://stackoverflow.com/questions/2683442/where-can-i-find-the-clamp-function-in-net#comment53011741_20443081)で指摘されているように、一回余分な比較が発生する余地があります。
23
+
24
+ 余分な比較を発生させず、かつ一行で書くのであれば、上記の投稿で、質問者さんが最初に
25
+
26
+ > I would like to clamp a value x to a range [a, b]:
27
+
28
+ > x = (x < a) ? a : ((x > b) ? b : x);
29
+
30
+ と書いているように、三項演算子の利用も検討されるとよいかと思います。
31
+
32
+ ---
9
33
  **追記1**
10
34
 
11
35
  ご質問の冒頭に、

15

テキスト追加

2018/08/10 21:56

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -11,7 +11,7 @@
11
11
  ご質問の冒頭に、
12
12
  > 座標(x, y)が・・・
13
13
 
14
- とありましたので、座標上の点を処理するコードのリファクタリングという観点で、以下を追記します。
14
+ とありましたので、座標上の点を処理するコードのリファクタという観点で、以下を追記します。やることは以下です。
15
15
 
16
16
  - 座標上の点クラス `Point` を作成
17
17
  - `Point`を拡張して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成

14

テキスト追加

2018/08/10 02:57

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -14,7 +14,7 @@
14
14
  とありましたので、座標上の点を処理するコードのリファクタリングという観点で、以下を追記します。
15
15
 
16
16
  - 座標上の点クラス `Point` を作成
17
- - `Point`を拡張して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成
17
+ - `Point`を拡張して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成
18
18
  - なお以下では、応用であることを明確にするため、`Point` インスタンスは、xyz軸を持つ3次元空間の点としています。
19
19
 
20
20
  上記にそって、作ったコードが以下です。

13

テキスト追加

2018/08/10 02:33

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -1,18 +1,24 @@
1
1
  こんにちは。
2
- 例えば以下でどうでしょう?
2
+ 以下でどうでしょう?
3
3
 
4
4
  ```javascript
5
5
  x = Math.min(COL-1, Math.max(0, x));
6
6
  y = Math.min(ROW-1, Math.max(0, y));
7
7
 
8
8
  ```
9
- 以下は蛇足です。
9
+ **追記1**
10
10
 
11
11
  ご質問の冒頭に、
12
12
  > 座標(x, y)が・・・
13
13
 
14
- とありましたので、座標上の点クラス `Point` 作成し、これを拡張して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成してみました。なお以下では、応用であることを明確にするため、`Point` インスタンスはxyz軸持つ3次元空間の点とています。
14
+ とありましたので、座標上の点を処理するコードのリファクグという観点で以下追記します。
15
15
 
16
+ - 座標上の点クラス `Point` を作成
17
+ - `Point`をを拡張して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成
18
+ - なお以下では、応用であることを明確にするため、`Point` インスタンスは、xyz軸を持つ3次元空間の点としています。
19
+
20
+ 上記にそって、作ったコードが以下です。
21
+
16
22
  ```javascript
17
23
  class Point {
18
24
  constructor(x, y, z) {
@@ -54,7 +60,7 @@
54
60
  [https://jsfiddle.net/jun68ykt/cs86vtj3/15/](https://jsfiddle.net/jun68ykt/cs86vtj3/15/)
55
61
 
56
62
  ---
57
- **追記**
63
+ **追記2**
58
64
 
59
65
  もうひとつ蛇足ですが、上記の`RestrictedPoint` の書き方として、アクセサを使う手もありそうです。
60
66
 

12

テキスト追加

2018/08/10 02:33

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -124,4 +124,4 @@
124
124
 
125
125
  [https://jsfiddle.net/jun68ykt/cs86vtj3/73/](https://jsfiddle.net/jun68ykt/cs86vtj3/73/)
126
126
 
127
- アクセサを使う利点としては、上記のコードの最後の2行に書いてあるように、`p2.x = 1000;` と代入しも、 `p2.x` は X座標の上限値の`99`を返すようにできることです。
127
+ アクセサを使う利点としては、上記のコードの最後の2行に書いてあるように、`p2.x = 1000;` と代入したつりでも、 `p2.x` は X座標の上限値の`99`を返すようにできることです。

11

テキスト追加

2018/08/10 02:21

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -6,9 +6,13 @@
6
6
  y = Math.min(ROW-1, Math.max(0, y));
7
7
 
8
8
  ```
9
+ 以下は蛇足です。
9
10
 
11
+ ご質問の冒頭に、
10
- 蛇足ですが、上記のように`Math.min`と`Math.max`を使った例として、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される、3次元空間の点`RestrictedPoint`を作成してみました。
12
+ > 座標(x, y)・・・
11
13
 
14
+ とありましたので、座標上の点クラス `Point` を作成し、これを拡張して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成してみました。なお以下では、応用であることを明確にするため、`Point` インスタンスは、xyz軸を持つ3次元空間の点としています。
15
+
12
16
  ```javascript
13
17
  class Point {
14
18
  constructor(x, y, z) {

10

テキスト追加

2018/08/10 02:20

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -86,22 +86,18 @@
86
86
  };
87
87
  }
88
88
 
89
- get x() {
89
+ get(axis) {
90
- const conf = this.constructor.config().x;
90
+ const conf = this.constructor.config()[axis];
91
- return Math.min(conf.max, Math.max(conf.min, this._x));
91
+ return Math.min(conf.max, Math.max(conf.min, this[`_${axis}`]));
92
92
  }
93
+
94
+ get x() { return this.get('x'); }
93
95
  set x(value) { this._x = value; }
94
96
 
95
- get y() {
96
- const conf = this.constructor.config().y;
97
+ get y() { return this.get('y'); }
97
- return Math.min(conf.max, Math.max(conf.min, this._y));
98
- }
99
98
  set y(value) { this._y = value; }
100
99
 
101
- get z() {
102
- const conf = this.constructor.config().z;
100
+ get z() { return this.get('z'); }
103
- return Math.min(conf.max, Math.max(conf.min, this._z));
104
- }
105
101
  set z(value) { this._z = value; }
106
102
 
107
103
  }
@@ -122,6 +118,6 @@
122
118
 
123
119
  以下に上記のコードを上げました。
124
120
 
125
- [https://jsfiddle.net/jun68ykt/cs86vtj3/70/](https://jsfiddle.net/jun68ykt/cs86vtj3/70/)
121
+ [https://jsfiddle.net/jun68ykt/cs86vtj3/73/](https://jsfiddle.net/jun68ykt/cs86vtj3/73/)
126
122
 
127
- 上記のコードの最後の2行に書いてあるように、`p2.x = 1000` と代入しても、 `p2.x` は X座標の上限値の`99`を返します。
123
+ アクセサを使う利点としては、上記のコードの最後の2行に書いてあるように、`p2.x = 1000;` と代入しても、 `p2.x` は X座標の上限値の`99`を返すようにできることです

9

テキスト修正

2018/08/10 02:03

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -122,6 +122,6 @@
122
122
 
123
123
  以下に上記のコードを上げました。
124
124
 
125
- [https://jsfiddle.net/cs86vtj3/68/](https://jsfiddle.net/cs86vtj3/68/)
125
+ [https://jsfiddle.net/jun68ykt/cs86vtj3/70/](https://jsfiddle.net/jun68ykt/cs86vtj3/70/)
126
126
 
127
127
  上記のコードの最後の2行に書いてあるように、`p2.x = 1000` と代入しても、 `p2.x` は X座標の上限値の`99`を返します。

8

テキスト追加

2018/08/10 01:53

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -122,6 +122,6 @@
122
122
 
123
123
  以下に上記のコードを上げました。
124
124
 
125
- [https://jsfiddle.net/cs86vtj3/66/](https://jsfiddle.net/cs86vtj3/66/)
125
+ [https://jsfiddle.net/cs86vtj3/68/](https://jsfiddle.net/cs86vtj3/68/)
126
126
 
127
127
  上記のコードの最後の2行に書いてあるように、`p2.x = 1000` と代入しても、 `p2.x` は X座標の上限値の`99`を返します。

7

テキスト追加

2018/08/10 01:52

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -122,6 +122,6 @@
122
122
 
123
123
  以下に上記のコードを上げました。
124
124
 
125
- [https://jsfiddle.net/cs86vtj3/65/](https://jsfiddle.net/cs86vtj3/65/)
125
+ [https://jsfiddle.net/cs86vtj3/66/](https://jsfiddle.net/cs86vtj3/66/)
126
126
 
127
127
  上記のコードの最後の2行に書いてあるように、`p2.x = 1000` と代入しても、 `p2.x` は X座標の上限値の`99`を返します。

6

テキスト追加

2018/08/10 01:40

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -47,4 +47,81 @@
47
47
  ```
48
48
 
49
49
  以下、上記を試行するサンプルです。
50
- [https://jsfiddle.net/jun68ykt/cs86vtj3/15/](https://jsfiddle.net/jun68ykt/cs86vtj3/15/)
50
+ [https://jsfiddle.net/jun68ykt/cs86vtj3/15/](https://jsfiddle.net/jun68ykt/cs86vtj3/15/)
51
+
52
+ ---
53
+ **追記**
54
+
55
+ もうひとつ蛇足ですが、上記の`RestrictedPoint` の書き方として、アクセサを使う手もありそうです。
56
+
57
+ ```javascript
58
+ class Point {
59
+ constructor(x=0, y=0, z=0) {
60
+ this._x = x;
61
+ this._y = y;
62
+ this._z = z;
63
+ }
64
+
65
+ get x() { return this._x; }
66
+ set x(value) { this._x = value; }
67
+
68
+ get y() { return this._y; }
69
+ set y(value) { this._y = value; }
70
+
71
+ get z() { return this._z; }
72
+ set z(value) { this._z = value; }
73
+
74
+ toString() {
75
+ return `(x: ${this.x}, y: ${this.y}, z: ${this.z})`;
76
+ }
77
+ }
78
+
79
+ class RestrictedPoint extends Point {
80
+
81
+ static config() {
82
+ return {
83
+ x: { min: 0, max: 99 }, // X座標は0以上99以下
84
+ y: { min: 0, max: 199 }, // Y座標は0以上199以下
85
+ z: { min: 100, max: 399 } // Z座標は100以上399以下
86
+ };
87
+ }
88
+
89
+ get x() {
90
+ const conf = this.constructor.config().x;
91
+ return Math.min(conf.max, Math.max(conf.min, this._x));
92
+ }
93
+ set x(value) { this._x = value; }
94
+
95
+ get y() {
96
+ const conf = this.constructor.config().y;
97
+ return Math.min(conf.max, Math.max(conf.min, this._y));
98
+ }
99
+ set y(value) { this._y = value; }
100
+
101
+ get z() {
102
+ const conf = this.constructor.config().z;
103
+ return Math.min(conf.max, Math.max(conf.min, this._z));
104
+ }
105
+ set z(value) { this._z = value; }
106
+
107
+ }
108
+
109
+ const p1 = new Point(-1, 230, 50);
110
+ console.log(`${p1}`); // => (x: -1, y: 230, z: 50)
111
+
112
+ p1.x = 1000;
113
+ console.log(p1.x); // => 1000
114
+
115
+ const p2 = new RestrictedPoint(-1, 230, 50);
116
+ console.log(`${p2}`); // => (x: 0, y: 199, z: 100)
117
+
118
+ p2.x = 1000;
119
+ console.log(p2.x); // => 99
120
+
121
+ ```
122
+
123
+ 以下に上記のコードを上げました。
124
+
125
+ [https://jsfiddle.net/cs86vtj3/65/](https://jsfiddle.net/cs86vtj3/65/)
126
+
127
+ 上記のコードの最後の2行に書いてあるように、`p2.x = 1000` と代入しても、 `p2.x` は X座標の上限値の`99`を返します。

5

テキスト修正

2018/08/10 01:38

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  ```
9
9
 
10
- 蛇足ですが、上記のように`Math.min`と`Math.max`を使った例として、3次元空間の点 `Point` を継承して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成してみました。
10
+ 蛇足ですが、上記のように`Math.min`と`Math.max`を使った例として、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される、3次元空間の点`RestrictedPoint`を作成してみました。
11
11
 
12
12
  ```javascript
13
13
  class Point {

4

テキスト修正

2018/08/09 23:24

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -26,9 +26,8 @@
26
26
 
27
27
  adjust() {
28
28
  for ( const [axis, value] of Object.entries(this)) {
29
- const maxValue = RestrictedPoint.config[axis].max;
30
- const minValue = RestrictedPoint.config[axis].min;
29
+ const config = this.constructor.config[axis];
31
- this[axis] = Math.min(maxValue, Math.max(minValue, value));
30
+ this[axis] = Math.min(config.max, Math.max(config.min, value));
32
31
  }
33
32
  }
34
33
  }
@@ -48,4 +47,4 @@
48
47
  ```
49
48
 
50
49
  以下、上記を試行するサンプルです。
51
- [https://jsfiddle.net/jun68ykt/cs86vtj3/11/](https://jsfiddle.net/jun68ykt/cs86vtj3/11/)
50
+ [https://jsfiddle.net/jun68ykt/cs86vtj3/15/](https://jsfiddle.net/jun68ykt/cs86vtj3/15/)

3

テキスト修正

2018/08/09 23:20

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -7,11 +7,8 @@
7
7
 
8
8
  ```
9
9
 
10
- ---
11
-
10
+ ですが、上記のように`Math.min`と`Math.max`を使った例として、3次元空間の点 `Point` を継承して、あらかじめ設定された最小値と最大値の範囲に収まるように各座標が調整される`RestrictedPoint`を作成してみました。
12
11
 
13
- 蛇足ですが、上記を使って、3次元座標の点 `Point` を継承して、各座標の最大値と最小値の範囲に収まるように調整される `RestrictedPoint` を作成してみました。
14
-
15
12
  ```javascript
16
13
  class Point {
17
14
  constructor(x, y, z) {

2

テキスト修正

2018/08/09 23:13

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -41,6 +41,13 @@
41
41
  y: { min: 0, max: 199 }, // Y座標は0以上199以下
42
42
  z: { min: 100, max: 399 } // Z座標は100以上399以下
43
43
  };
44
+
45
+ const p1 = new Point(-1, 230, 50);
46
+ console.log(p1); // => Object {x=-1, y=230, z=50}
47
+
48
+ const p2 = new RestrictedPoint(-1, 230, 50);
49
+ console.log(p2); // => Object {x=0, y=199, z=100}
50
+
44
51
  ```
45
52
 
46
53
  以下、上記を試行するサンプルです。

1

テキスト修正

2018/08/09 20:30

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -5,4 +5,43 @@
5
5
  x = Math.min(COL-1, Math.max(0, x));
6
6
  y = Math.min(ROW-1, Math.max(0, y));
7
7
 
8
- ```
8
+ ```
9
+
10
+ ---
11
+ 補足
12
+
13
+ 蛇足ですが、上記を使って、3次元座標の点 `Point` を継承して、各座標の最大値と最小値の範囲に収まるように調整される `RestrictedPoint` を作成してみました。
14
+
15
+ ```javascript
16
+ class Point {
17
+ constructor(x, y, z) {
18
+ this.x = x;
19
+ this.y = y;
20
+ this.z = z;
21
+ }
22
+ }
23
+
24
+ class RestrictedPoint extends Point {
25
+ constructor(x, y, z) {
26
+ super(x, y, z);
27
+ this.adjust();
28
+ }
29
+
30
+ adjust() {
31
+ for ( const [axis, value] of Object.entries(this)) {
32
+ const maxValue = RestrictedPoint.config[axis].max;
33
+ const minValue = RestrictedPoint.config[axis].min;
34
+ this[axis] = Math.min(maxValue, Math.max(minValue, value));
35
+ }
36
+ }
37
+ }
38
+
39
+ RestrictedPoint.config = {
40
+ x: { min: 0, max: 99 }, // X座標は0以上99以下
41
+ y: { min: 0, max: 199 }, // Y座標は0以上199以下
42
+ z: { min: 100, max: 399 } // Z座標は100以上399以下
43
+ };
44
+ ```
45
+
46
+ 以下、上記を試行するサンプルです。
47
+ [https://jsfiddle.net/jun68ykt/cs86vtj3/11/](https://jsfiddle.net/jun68ykt/cs86vtj3/11/)