回答編集履歴

1

コメントへの回答を追記

2022/11/17 23:01

投稿

退会済みユーザー
test CHANGED
@@ -28,3 +28,148 @@
28
28
  [ 9, 19 ],
29
29
  [ 10, 20 ] ]
30
30
  ```
31
+
32
+
33
+ ### 追記
34
+
35
+ コメントに返信します。
36
+
37
+ #### 前提
38
+
39
+ a), b) に答える前にまず、`.filter(([v]) => v).map(row => row.filter(v => v))` の処理をやらないで、getValues() するところまでにして
40
+ ```javascript
41
+ const values = sheet.getRange(4,4,19,3).getValues();
42
+ ```
43
+ としたとすると、`values` には以下のような配列が入ってきます。
44
+ ```
45
+ [
46
+ [ 1, '', 11 ], [ '', '', '' ], [ 2, '', 12 ], [ '', '', '' ], [ 3, '', 13 ], [ '', '', '' ], [ 4, '', 14 ], [ '', '', '' ], [ 5, '', 15 ], [ '', '', '' ],
47
+ [ 6, '', 16 ], [ '', '', '' ], [ 7, '', 17 ], [ '', '', '' ], [ 8, '', 18 ], [ '', '', '' ], [ 9, '', 19 ], [ '', '', '' ], [ 10, '', 20 ]
48
+ ]
49
+ ```
50
+ すなわち、`values` は以下のようなものになっています。
51
+ (1) 全体が配列であり、
52
+ (2) その要素もまた配列であり、
53
+ (3) 要素の配列は長さが3で、次の2とおりの場合がある。
54
+ - [整数, '', 整数] (ただし整数は1以上)
55
+ - ['', '', '']
56
+
57
+ 上記のような配列に対して以下の2つの処理[A], [B] を行います。
58
+
59
+ [A] `.filter(([v]) => v)` によって要素 `['', '', ''] ` を取り除いた、以下のような配列を得る。
60
+
61
+ ```
62
+ [ [ 1, '', 11 ], [ 2, '', 12 ], [ 3, '', 13 ], [ 4, '', 14 ], [ 5, '', 15 ], [ 6, '', 16 ], [ 7, '', 17 ], [ 8, '', 18 ], [ 9, '', 19 ], [ 10, '', 20 ] ]
63
+ ```
64
+
65
+ [B] 処理[A]の結果得られた上記の配列の各要素である配列 `[整数, '', 整数]` から空文字列を除いた `[整数, 整数]` を各要素とする配列
66
+
67
+ ```
68
+ [ [ 1, 11 ], [ 2, 12 ], [ 3, 13 ], [ 4, 14 ], [ 5, 15 ], [ 6, 16 ], [ 7, 17 ], [ 8, 18 ], [ 9, 19 ], [ 10, 20 ] ]
69
+ ```
70
+
71
+ を得る。
72
+
73
+ 上記の2つの処理[A], [B]のうち [A]を行っているのが `.filter(([v]) => v)` で、[B]を行っているのが `.map(row => row.filter(v => v))` です。
74
+
75
+ 以上をふまえて質問に回答します。
76
+
77
+ #### 質問 a
78
+
79
+ > a) .filter(([v]) => v) 
80
+ > ここでフィルタの条件を指定しているんだろうなと推測しているのですが、
81
+ > ([v]) => v は何を意味しているのかが分かりません。
82
+
83
+ filterメソッドには引数として関数を渡します。`([v]) => v` もまた関数です。これはアロー関数であり、かつ引数部分に[分割代入](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)を使っています。この関数をアローと分割代入を使わないで書くと以下のようになります。
84
+
85
+ ```javascript
86
+ function (ary) {
87
+ return ary[0];
88
+ }
89
+ ```
90
+ すなわち、「配列を引数に取り、その配列の先頭要素を返す関数」です。これをアローと分割代入を使えば
91
+ ```javascript
92
+ ([v]) => v
93
+ ```
94
+ とコードを詰めて書けます。
95
+
96
+ なぜ、このような「配列を引数に取り、その配列の先頭要素を返す関数」を filter に渡せば、今回の質問において処理[A] を行うfilter条件として意図通りの結果になるのか?が分からない場合はまたご質問ください。(ちなみに この関数が先の[A] の処理を行うfilter条件として適切であることは、D列の数字が1以上であることを前提にしています。もしD列の数字が0始まりだとうまくいきません。これについては後述の **補足1** も併せて確認するとよいでしょう)
97
+
98
+
99
+
100
+ #### 質問 b
101
+
102
+ > b) .map(row => row.filter(v => v));
103
+ > 上記a)と同様、row => row.filter(v => v)部が何を意味しているのかが
104
+ > わかりません。
105
+  
106
+ `.map(row => row.filter(v => v))` では先に書いた処理[B] を行います。つまり、配列
107
+ ```
108
+ [ [ 1, '', 11 ], [ 2, '', 12 ], [ 3, '', 13 ], [ 4, '', 14 ], [ 5, '', 15 ], [ 6, '', 16 ], [ 7, '', 17 ], [ 8, '', 18 ], [ 9, '', 19 ], [ 10, '', 20 ] ]
109
+ ```
110
+ から
111
+ ```
112
+ [ [ 1, 11 ], [ 2, 12 ], [ 3, 13 ], [ 4, 14 ], [ 5, 15 ], [ 6, 16 ], [ 7, 17 ], [ 8, 18 ], [ 9, 19 ], [ 10, 20 ] ]
113
+ ```
114
+ を得る処理です。この処理では処理前と処理後の(外側の)配列の要素数はともに10個で変わらないです。外側の配列の各要素である内側の配列(例 `[1, '', 11]`)に対して「要素として含まれる空文字列を除去する」という処理を行った配列(例 `[1, 11]`)を新たな要素とする配列を得る、という処理を行います。
115
+
116
+ このような、「ある配列の各要素に何らかの処理を行った結果の値を要素とする配列を得たい」という場合に使うのは [map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)メソッドです。
117
+
118
+ mapメソッドには「各要素を何か別のものにする関数」を引数として渡しますが、今回の場合は各要素もまた配列で、処理として「(要素である長さ3の)配列から空文字列を除いた配列を返す関数」をmapメソッドに渡せばよいことになります。そのような関数をアローを使わないで書くと以下のようになります。今回はスプレッドシートが元データなので引数の名前を `row` とします。
119
+
120
+ ```javascript
121
+ function (row) {
122
+ const filteredAry = row.filter(
123
+ function(v) {
124
+ return v;
125
+ }
126
+ );
127
+
128
+ return filteredAry;
129
+ }
130
+ ```
131
+ 上記の関数を、アローを使いかつ中間の変数 `filteredAry` を無くすことで `return`を省略できて、回答のコードにある
132
+ ```javascript
133
+ row => row.filter(v => v)
134
+ ```
135
+ と書けます。これを map に渡すことで、配列
136
+ ```
137
+ [ [ 1, '', 11 ], [ 2, '', 12 ], [ 3, '', 13 ], [ 4, '', 14 ], [ 5, '', 15 ], [ 6, '', 16 ], [ 7, '', 17 ], [ 8, '', 18 ], [ 9, '', 19 ], [ 10, '', 20 ] ]
138
+ ```
139
+ から最終目的の配列
140
+ ```
141
+ [ [ 1, 11 ], [ 2, 12 ], [ 3, 13 ], [ 4, 14 ], [ 5, 15 ], [ 6, 16 ], [ 7, 17 ], [ 8, 18 ], [ 9, 19 ], [ 10, 20 ] ]
142
+ ```
143
+ が得られます。
144
+
145
+
146
+ #### 補足1
147
+ 先述したとおり、
148
+
149
+ ```javascript
150
+ row => row.filter(v => v)
151
+ ```
152
+ という関数に引数として配列を渡すと、その配列に要素として含まれる空文字列が除去された配列が得られますが、除去の対象になるのは空文字列だけではありません。空文字列のほかに何が除去されるか調べて確認してみるとより理解が深まるかもしれません。
153
+
154
+ #### 補足2
155
+
156
+ すでに回答したコードでは 処理[B] を行うために mapメソッドの引数に
157
+ ```javascript
158
+ row => row.filter(v => v)
159
+ ```
160
+ という関数を渡しましたが、引数の`row` には `[ 1, '', 11 ]` といった長さが3の配列が渡されてきて、この配列の必ず2番目の要素である空文字列を除いた配列を返せばよいということが分かっているので、filter を使わずに 処理[A] のコードでも使った、関数の引数の分割代入による受け取りを使った以下の関数
161
+ ```javascript
162
+ ([x, _, y]) => [x, y]
163
+ ```
164
+ をmapの引数に渡しても [B] の処理として意図した結果を得られます。
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+