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

回答編集履歴

11

テキスト修正

2020/01/22 01:46

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -99,7 +99,7 @@
99
99
  entries.filter(([key, value]) => {
100
100
  // 何らかの判定ロジック
101
101
  retrurn trueまたはfalse
102
- });
102
+ })
103
103
  ```
104
104
 
105
105
  `function fetch_sub_industries(industry_id)` では、プロパティのキーが、`industry_id` と等しいかだけを見ればよいので、`value` は不要で、`key`のほうは id と呼ばれる値なので
@@ -108,7 +108,7 @@
108
108
  entries.filter(([id]) => {
109
109
  // 何らかの判定ロジック
110
110
  retrurn trueまたはfalse
111
- });
111
+ })
112
112
  ```
113
113
 
114
114
 
@@ -119,7 +119,7 @@
119
119
  ```javascript
120
120
  entries.filter(([id]) => {
121
121
  return id !== industry_id
122
- });
122
+ })
123
123
  ```
124
124
  と書けばよさそうですが、これだと、うまくいきません。
125
125
  なぜなら、関数`fetch_sub_industries` の引数 `industry_id` のほうは文字列ではなく、たとえば `1` だったりの整数が渡され、他方、
@@ -127,7 +127,7 @@
127
127
  ```javascript
128
128
  entries.filter(([id]) => {
129
129
  return id !== industry_id
130
- });
130
+ })
131
131
  ```
132
132
  と書いた場合の filter のループで呼ばれる関数の引数(の配列要素の) `id` には `"1"` だったりの文字列が渡されてくるため、
133
133
 
@@ -154,17 +154,17 @@
154
154
  ```javascript
155
155
  entries.filter(([id]) => {
156
156
  return +id !== industry_id
157
- });
157
+ })
158
158
  ```
159
159
  とすれば、意図通りに filter が機能します。さらに、アロー関数の本体が1行であり return で値を返しているので、上記を詰めて、
160
160
  ```javascript
161
- entries.filter(([id]) => +id !== industry_id);
161
+ entries.filter(([id]) => +id !== industry_id)
162
162
  ```
163
163
  と書いたものが、回答に挙げたコードになります。
164
164
 
165
165
  ちなみに、もし、`id` の型に合わせて、文字列の比較にするならば、`industry_id` のほうを文字列にする必要があるので、たとえば
166
166
  ```javascript
167
- entries.filter(([id]) => id !== `${industry_id}`);
167
+ entries.filter(([id]) => id !== `${industry_id}`)
168
168
  ```
169
169
  のようにします。
170
170
  - **動作確認用 CodePen: ** [https://codepen.io/jun68ykt/pen/vYEvWpB?editors=0012](https://codepen.io/jun68ykt/pen/vYEvWpB?editors=0012)

10

テキスト修正

2020/01/22 01:46

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -112,7 +112,7 @@
112
112
  ```
113
113
 
114
114
 
115
- と書けます。
115
+ と書いて、`id`という変数名で `["1", "スポーツ"]` の `"1"` を受取ります。
116
116
  次に、`// 何らかの判定ロジック` の部分を書いて、その結果を反映して true かfalse を返すようにします。
117
117
  `id` が `function fetch_sub_industries` に渡される `industry_id` に等しくない場合にのみ、filter によって残されればよいので、
118
118
 

9

テキスト修正

2020/01/22 00:21

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -226,6 +226,7 @@
226
226
  ・・・
227
227
  }
228
228
 
229
+ f(["1", "スポーツ"]);
229
230
  ```
230
231
  と書くことで、`id` と `name` に直接、配列の先頭と2番目の要素が得られます。これは、配列の分割代入を、関数の引数に使った書き方です。分割代入については以下に説明されています。
231
232
 

8

テキスト修正

2020/01/21 23:57

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -94,7 +94,7 @@
94
94
 
95
95
  上記の配列 `entries` を filter でループさせるときに、filter の引数として与える関数には、上記の
96
96
  `["1", "スポーツ"]`
97
- という形、すなわち長さが2で先頭要素が元のオブジェクトのプロパティのキー(文字列です)、二番目の要素がプロパティの値である配列が引数として渡されてくるので、以下のようにすれば、`key`, `value` という変数名で、この配列の要素を受け取れます。
97
+ という形、すなわち長さが2で先頭要素が元のオブジェクトのプロパティのキー(文字列です)、二番目の要素がプロパティの値である配列が引数として渡されてくるので、以下のようにすれば、`key`, `value` という変数名で、この配列の要素を受け取れます。(以下のコードで `[key, value]` という書き方は分割代入と呼ばれ、追記5 に説明しました。)
98
98
  ```javascript
99
99
  entries.filter(([key, value]) => {
100
100
  // 何らかの判定ロジック

7

テキスト修正

2020/01/21 23:54

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -244,6 +244,6 @@
244
244
  }
245
245
  ```
246
246
 
247
- 上記では、、`Object.entries` で得られる配列を `for ・・・ of`のループで得るときに、`・・・` の部分を`[key, value]` と書くことで分割代入を使い、キーと値を得ています。
247
+ 上記では、、`Object.entries` で得られる配列の要素を `for ・・・ of`のループで得るときに、`・・・` の部分を`[key, value]` と書くことで分割代入を使い、キーと値を得ています。
248
248
 
249
249
  以上、参考になれば幸いです。

6

テキスト修正

2020/01/21 23:36

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -195,5 +195,55 @@
195
195
  `id != industry_id`
196
196
  というコードを書くとESLintに警告されるので、型を合わせて `===` および `!==` を使うほうに慣れてきます。(実際私は、ここ数年、業務では `==` および `!=` をほとんど使ってないです。)
197
197
 
198
+ ### 追記5
198
199
 
200
+ もう一点、
201
+
202
+ > this.industriesが
203
+ [[1: "スポーツ"], [2: "メディア"], [3: "建設"]]
204
+ のようになっていて、
205
+ .filter(([id]) =>
206
+ で1,2,3が回るようになる?とすれば、なぜこれで1,2,3が回るのか。
207
+
208
+ についてですが、2つの要素を持つ配列 `["1", "スポーツ"]` を引数にとる関数を書くときに、この配列を `ary`という引数で受けて、
209
+
210
+ ```javascript
211
+ const f = (ary) => {
212
+ const id = ary[0];  // "1"
213
+ const name = ary[1]; // "スポーツ"
214
+ ・・・
215
+ }
216
+
217
+ f(["1", "スポーツ"]);
218
+
219
+ ```
220
+ と書くこともできますが、引数の `ary` を `[id, name]` として
221
+
222
+ ```javascript
223
+ const f = ([id, name]) => {
224
+ console.log(id); //=> "1"
225
+ console.log(name); //=> "スポーツ"
226
+ ・・・
227
+ }
228
+
229
+ ```
230
+ と書くことで、`id` と `name` に直接、配列の先頭と2番目の要素が得られます。これは、配列の分割代入を、関数の引数に使った書き方です。分割代入については以下に説明されています。
231
+
232
+ - MDN: [分割代入](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
233
+
234
+ また、MDNの[Object.entriesの説明](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) の冒頭にも、以下のようなサンプルがあります。
235
+
236
+ ```javascript
237
+ const object1 = {
238
+ a: 'somestring',
239
+ b: 42
240
+ };
241
+
242
+ for (let [key, value] of Object.entries(object1)) {
243
+ console.log(`${key}: ${value}`);
244
+ }
245
+ ```
246
+
247
+ 上記では、、`Object.entries` で得られる配列を `for ・・・ of`のループで得るときに、`・・・` の部分を`[key, value]` と書くことで分割代入を使い、キーと値を得ています。
248
+
199
249
  以上、参考になれば幸いです。

5

テキスト修正

2020/01/21 23:33

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -75,7 +75,7 @@
75
75
 
76
76
  - **動作確認用 CodePen: ** [https://codepen.io/jun68ykt/pen/qBELPgY?editors=0012](https://codepen.io/jun68ykt/pen/qBELPgY?editors=0012)
77
77
 
78
- すなわち、`this.industries` のプロパティのキーは、 1,2,3 という整数値ではなく、文字列の 1 , 2, 3 として保持されています。
78
+ すなわち、`this.industries` のプロパティのキーは、 1,2,3 という整数値ではなく、文字列の "1" , "2", "3" として保持されています。
79
79
 
80
80
  同様に、一番初めに挙げた回答コード
81
81
 

4

テキスト修正

2020/01/21 23:07

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -34,9 +34,9 @@
34
34
  - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/abzPdgm?editors=0012](https://codepen.io/jun68ykt/pen/abzPdgm?editors=0012)
35
35
 
36
36
 
37
- 以上、参考になれば幸いです。
38
37
 
39
38
 
39
+
40
40
  ### 追記3
41
41
 
42
42
 
@@ -44,4 +44,156 @@
44
44
 
45
45
  以下、そのサンプルです。
46
46
 
47
- - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/QWwzNGL?editors=1010](https://codepen.io/jun68ykt/pen/QWwzNGL?editors=1010)
47
+ - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/QWwzNGL?editors=1010](https://codepen.io/jun68ykt/pen/QWwzNGL?editors=1010)
48
+
49
+
50
+ ### 追記4
51
+
52
+
53
+ コメントから頂きました
54
+
55
+ > ソースをみて不明な点があり、
56
+
57
+ について回答します。
58
+
59
+
60
+ まず、
61
+
62
+ MDNの [JavaScript のデータ型とデータ構造](https://developer.mozilla.org/ja/docs/Web/JavaScript/Data_structures) の中にある、**Object** のセクションのプロパティの説明に、以下のように書かれています。
63
+
64
+ > キー値は String 値または Symbol 値です。
65
+
66
+ これを確かめるために、
67
+
68
+ ```javascript
69
+ this.industries = { 1: "スポーツ", 2: "メディア", 3: "建設" };
70
+
71
+ console.log(Object.keys(this.industries));
72
+ ```
73
+
74
+ とすると、以下で確認できるように、 `[ 1, 2, 3 ]` ではなく、 `["1", "2", "3"]` と表示されます。
75
+
76
+ - **動作確認用 CodePen: ** [https://codepen.io/jun68ykt/pen/qBELPgY?editors=0012](https://codepen.io/jun68ykt/pen/qBELPgY?editors=0012)
77
+
78
+ すなわち、`this.industries` のプロパティのキーは、 1,2,3 という整数値ではなく、文字列の “1” , “2”, “3” として保持されています。
79
+
80
+ 同様に、一番初めに挙げた回答コード
81
+
82
+ - **動作確認用 CodePen: ** [https://codepen.io/jun68ykt/pen/JjowGyG?editors=0012](https://codepen.io/jun68ykt/pen/JjowGyG?editors=0012)
83
+
84
+ にある、以下の行
85
+ ```javascript
86
+ let entries = Object.entries(this.industries);
87
+ ```
88
+
89
+ で得られる `entries` を console.log で表示すると、以下のようになり、エントリーのキーは、"1", "2", "3" と、文字列として取得されてくることが確認できると思います。
90
+
91
+ ```
92
+ [["1", "スポーツ"], ["2", "メディア"], ["3", "建設"]]
93
+ ```
94
+
95
+ 上記の配列 `entries` を filter でループさせるときに、filter の引数として与える関数には、上記の
96
+ `["1", "スポーツ"]`
97
+ という形、すなわち長さが2で先頭要素が元のオブジェクトのプロパティのキー(文字列です)、二番目の要素がプロパティの値である配列が引数として渡されてくるので、以下のようにすれば、`key`, `value` という変数名で、この配列の要素を受け取れます。
98
+ ```javascript
99
+ entries.filter(([key, value]) => {
100
+ // 何らかの判定ロジック
101
+ retrurn trueまたはfalse
102
+ });
103
+ ```
104
+
105
+ `function fetch_sub_industries(industry_id)` では、プロパティのキーが、`industry_id` と等しいかだけを見ればよいので、`value` は不要で、`key`のほうは id と呼ばれる値なので
106
+
107
+ ```javascript
108
+ entries.filter(([id]) => {
109
+ // 何らかの判定ロジック
110
+ retrurn trueまたはfalse
111
+ });
112
+ ```
113
+
114
+
115
+ と書けます。
116
+ 次に、`// 何らかの判定ロジック` の部分を書いて、その結果を反映して true かfalse を返すようにします。
117
+ `id` が `function fetch_sub_industries` に渡される `industry_id` に等しくない場合にのみ、filter によって残されればよいので、
118
+
119
+ ```javascript
120
+ entries.filter(([id]) => {
121
+ return id !== industry_id
122
+ });
123
+ ```
124
+ と書けばよさそうですが、これだと、うまくいきません。
125
+ なぜなら、関数`fetch_sub_industries` の引数 `industry_id` のほうは文字列ではなく、たとえば `1` だったりの整数が渡され、他方、
126
+
127
+ ```javascript
128
+ entries.filter(([id]) => {
129
+ return id !== industry_id
130
+ });
131
+ ```
132
+ と書いた場合の filter のループで呼ばれる関数の引数(の配列要素の) `id` には `"1"` だったりの文字列が渡されてくるため、
133
+
134
+ ```
135
+ id !== industry_id
136
+ ```
137
+ は(両辺の型が違うので、値を比較するまでもなく、)必ずtrueになります。したがって `fetch_sub_industries(1)` としたときも `["1", "スポーツ"]` が除外されず、結果として`this.industries` は元のオブジェクトの3つのエントリ(キーと値の組)をどれも持つものとなってしまいます。以下で確認できます。
138
+
139
+ - **動作確認用 CodePen: ** [https://codepen.io/jun68ykt/pen/rNaoYjJ?editors=0012](https://codepen.io/jun68ykt/pen/rNaoYjJ?editors=0012)
140
+
141
+
142
+ `!==` によって意図した判定が行われるには、両辺の型を揃える必要がありますが、回答のコードでは、関数`fetch_sub_industries` の引数`industry_id`は整数値が渡されることを前提として、両辺を数値にあわせることにしました。そのためには filter のループで使われる `id` のほうを文字列から数値に変換しなければなりません。数字の文字列である `id` を数値に変換する方法としては、`Number(id)` や `parseInt(id)` (より厳密には、`parseInt(id, 10)` ) とすればよいですが、もっと簡単に書く方法として
143
+
144
+ ```
145
+ +id
146
+ ```
147
+
148
+ と書くことでも数値が得られます。 これにより、`id` がたとえば `"1"` ならば、数値の `1` が得られます。このような `+` は単項加算(unary plus)と呼ばれます。以下は MDN の単項加算の説明です。
149
+
150
+ - MDN: [単項加算 (+)](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_plus_)
151
+
152
+ 単項加算を使って、`!==` の両辺を数値にあわせて、
153
+
154
+ ```javascript
155
+ entries.filter(([id]) => {
156
+ return +id !== industry_id
157
+ });
158
+ ```
159
+ とすれば、意図通りに filter が機能します。さらに、アロー関数の本体が1行であり return で値を返しているので、上記を詰めて、
160
+ ```javascript
161
+ entries.filter(([id]) => +id !== industry_id);
162
+ ```
163
+ と書いたものが、回答に挙げたコードになります。
164
+
165
+ ちなみに、もし、`id` の型に合わせて、文字列の比較にするならば、`industry_id` のほうを文字列にする必要があるので、たとえば
166
+ ```javascript
167
+ entries.filter(([id]) => id !== `${industry_id}`);
168
+ ```
169
+ のようにします。
170
+ - **動作確認用 CodePen: ** [https://codepen.io/jun68ykt/pen/vYEvWpB?editors=0012](https://codepen.io/jun68ykt/pen/vYEvWpB?editors=0012)
171
+
172
+
173
+ 上記のように、厳密な比較の `!==` を使うと、数値か文字列のいずれかに型を合わせる必要がありますが、これがやや煩雑と思えば、厳密でない比較の `!=` を使って
174
+
175
+ ```javascript
176
+ id != industry_id
177
+ ```
178
+
179
+ と書くことで、文字列である `id` のほうが、数値(Number型)に変換されてから、その値が、`industry_id` と等しくないかを判定します。`!==` と `!=` の違い(あるいは `===` と `==` の違い)を確認するには、以下に説明があります。
180
+
181
+ - MDN: [等価演算子の使用](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Using_the_equality_operators)
182
+
183
+
184
+ 上記のような場合、 `id` と `industry_id` とで、いずれかの型を他方に、(たとえば上記のように `id` に単項加算を追加して、)明示的に合わせて `===` や `!==` で比較したほうがよいのか、あるいは `==` や `!=` を使って、型を明示的に合わせることを不要にして比較するほうがよいのかについては、「時と場合による」という考え方もできますが、ひとつのガイドとして、javascript のコードチェックツールの ESLint の様々なルールの中に
185
+
186
+ - `==` および `!=` は使わないようにして、 `===` および `!==` を使うべき
187
+
188
+ という、以下のルール
189
+
190
+ - ESLint: [Require === and !== (eqeqeq)](https://eslint.org/docs/rules/eqeqeq)
191
+
192
+ > It is considered good practice to use the type-safe equality operators === and !== instead of their regular counterparts == and !=.
193
+
194
+ があります。ですので、(私もそうですが)ふだん ESLint を効かせながらコードを書いていると、 `!=` を使った
195
+ `id != industry_id`
196
+ というコードを書くとESLintに警告されるので、型を合わせて `===` および `!==` を使うほうに慣れてきます。(実際私は、ここ数年、業務では `==` および `!=` をほとんど使ってないです。)
197
+
198
+
199
+ 以上、参考になれば幸いです。

3

テキスト修正

2020/01/21 23:04

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -34,4 +34,14 @@
34
34
  - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/abzPdgm?editors=0012](https://codepen.io/jun68ykt/pen/abzPdgm?editors=0012)
35
35
 
36
36
 
37
- 以上、参考になれば幸いです。
37
+ 以上、参考になれば幸いです。
38
+
39
+
40
+ ### 追記3
41
+
42
+
43
+ 上記の回答は、ご質問にある関数 `fetch_sub_industries` を、ご質問にある意図通りにするための修正案ですが、2つの`<select>` を連動させて、1つ目の `seelct` で選ばれた選択肢を、2つ目の `select` では表示させないようにすることが主目的なのであれば、2つの`select`は両方とも常に`option`を3つ持つようにしておき、1つ目で選ばれた選択肢を2つ目で非表示にするために、CSSの `display` を `none` にするという手もあるかと思います。
44
+
45
+ 以下、そのサンプルです。
46
+
47
+ - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/QWwzNGL?editors=1010](https://codepen.io/jun68ykt/pen/QWwzNGL?editors=1010)

2

テキスト修正

2020/01/21 14:27

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -1,16 +1,15 @@
1
1
  こんにちは
2
2
 
3
- `filter`を使うのであれば、以下のようにすればよいかと思います。
3
+ ご質問に挙げられているコードの意図に沿って、関数 `fetch_sub_industries` は、 `this.industries` を新しいオブジェクトで書き換えるものとします。この前提で、`filter`を使うのであれば、以下のようにすればよいかと思います。
4
4
 
5
5
  ```javascript
6
6
  function fetch_sub_industries(industry_id) {
7
7
  let entries = Object.entries(this.industries);
8
- entries = entries.filter(([id, name]) => +id !== industry_id);
8
+ entries = entries.filter(([id]) => +id !== industry_id);
9
- return Object.fromEntries(entries);
9
+ this.industries = Object.fromEntries(entries);
10
10
  }
11
-
12
11
  ```
13
- - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/eYmbNQR?editors=0012](https://codepen.io/jun68ykt/pen/eYmbNQR?editors=0012)
12
+ - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/JjowGyG?editors=0012](https://codepen.io/jun68ykt/pen/JjowGyG?editors=0012)
14
13
 
15
14
  ### 追記
16
15
 
@@ -18,9 +17,21 @@
18
17
 
19
18
  ```javascript
20
19
  function fetch_sub_industries(industry_id) {
21
- return _.omit(this.industries, industry_id);
20
+ this.industries = _.omit(this.industries, industry_id);
22
21
  }
23
22
  ```
24
- - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/qBELOaL?editors=0012](https://codepen.io/jun68ykt/pen/qBELOaL?editors=0012)
23
+ - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/wvBRMqj?editors=0012](https://codepen.io/jun68ykt/pen/wvBRMqj?editors=0012)
25
24
 
25
+ ### 追記2
26
+
27
+ 新しいオブジェクトを作って、`this.industries` に再度代入するのではなく、現状の `this.industries` から、単に `industry_id` で指定されるプロパティを除去すればよいのであれば、以下でもよいかと思います。
28
+
29
+ ```javascript
30
+ function fetch_sub_industries(industry_id) {
31
+ delete this.industries[industry_id];
32
+ }
33
+ ```
34
+ - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/abzPdgm?editors=0012](https://codepen.io/jun68ykt/pen/abzPdgm?editors=0012)
35
+
36
+
26
37
  以上、参考になれば幸いです。

1

テキスト修正

2020/01/21 13:49

投稿

jun68ykt
jun68ykt

スコア9058

answer CHANGED
@@ -10,4 +10,17 @@
10
10
  }
11
11
 
12
12
  ```
13
- - 動作確認用 CodePen: [https://codepen.io/jun68ykt/pen/eYmbNQR?editors=0012](https://codepen.io/jun68ykt/pen/eYmbNQR?editors=0012)
13
+ - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/eYmbNQR?editors=0012](https://codepen.io/jun68ykt/pen/eYmbNQR?editors=0012)
14
+
15
+ ### 追記
16
+
17
+ 配列やオブジェクトの操作で便利なライブラリ lodash の [_.omit](https://lodash.com/docs/#omit) を使うと、以下のように手短かに書けます。
18
+
19
+ ```javascript
20
+ function fetch_sub_industries(industry_id) {
21
+ return _.omit(this.industries, industry_id);
22
+ }
23
+ ```
24
+ - **動作確認用 CodePen: **[https://codepen.io/jun68ykt/pen/qBELOaL?editors=0012](https://codepen.io/jun68ykt/pen/qBELOaL?editors=0012)
25
+
26
+ 以上、参考になれば幸いです。