回答編集履歴

12

テキスト修正

2020/06/20 10:08

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -403,3 +403,43 @@
403
403
 
404
404
 
405
405
  となってしまい、B-2 には、二つの親、A-1 と A-2 があることになってしまいます。ですが、先のstackoverflow の投稿では、各ノードの親は、木構造の定義に沿って、(最大で)一個であるようなノードの一次元配列を木構造化するコードでした。これを踏まえて、それでも[ベストアンサー](https://stackoverflow.com/a/18018037) の `function list_to_tree(list)` を使おうとすると、id として A-1やB-2だったりの文字列はそのまま使えず、「A-1 が親のB-1 と、A-2が親のB-2とは、別物である」という考え方を採り入れて、それらに異なる id を設ける必要があり、これはけっこう煩雑な作業となりそうです。
406
+
407
+
408
+
409
+ ### 追記4
410
+
411
+
412
+
413
+ 上記の追記3で書いた、[function list_to_tree(list)](https://stackoverflow.com/a/18018037) を使うための
414
+
415
+
416
+
417
+ > 「A-1 が親のB-1 と、A-2が親のB-2とは、別物である」という考え方を採り入れて、それらに異なる id
418
+
419
+
420
+
421
+ を実装したコード例を挙げておきます。以下になります。(※ `list_to_tree(list)` は、そのままコピペしてきたもので、手を加えていません)
422
+
423
+
424
+
425
+ - **動作確認用CodePen:** [https://codepen.io/jun68ykt/pen/zYrNQzv?editors=0012](https://codepen.io/jun68ykt/pen/zYrNQzv?editors=0012)
426
+
427
+
428
+
429
+ 具体的には、たとえば、`[ 'A-2', 'B-2', 'C-10' ]` の `C-10` から、以下のようなノードオブジェクトを作成します。
430
+
431
+ ```javascript
432
+
433
+ { id: 'A-2/B-2/C-10', parentId: 'A-2/B-2', label: 'C-10' }
434
+
435
+ ```
436
+
437
+ また、トップレベルの `A-2` からは、 parentId に文字列の `"0"` を入れた、以下のオブジェクトを作成します。
438
+
439
+ ```javascript
440
+
441
+ { id: 'A-2', parentId: '0', label: 'A-2' }
442
+
443
+ ```
444
+
445
+ 上記のようなオブジェクトを要素とする一次元配列を、元のテーブルデータから作成すると、その配列を [function list_to_tree(list)](https://stackoverflow.com/a/18018037) に渡すことができて、木構造化した配列を返してくれますので、それをさらに望ましい形にフォーマットして結果を得ています。

11

テキスト修正

2020/06/20 10:08

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -343,3 +343,63 @@
343
343
 
344
344
 
345
345
  - **動作確認用CodePen:** [https://codepen.io/jun68ykt/pen/oNbBaKE?editors=0012](https://codepen.io/jun68ykt/pen/oNbBaKE?editors=0012)
346
+
347
+
348
+
349
+ ### 追記3
350
+
351
+
352
+
353
+ 先に書いた、追記1 で、stackoverflow の投稿 [Build tree array from flat array in javascript](https://stackoverflow.com/questions/18017869) を挙げましたが、これの回答の中の[ベストアンサー](https://stackoverflow.com/a/18018037) の `function list_to_tree(list)` を使えそうか、ちょっとスパイクしてみましたが、問題があり簡単にはできそうもなかったです。その説明を以下、記載します。
354
+
355
+
356
+
357
+ 元のテーブルのデータ配列は
358
+
359
+ ```
360
+
361
+ [
362
+
363
+ [ '列A', '列B', '列C' ],
364
+
365
+ [ 'A-1', 'B-1', 'C-1' ],
366
+
367
+ [ 'A-1', 'B-1', 'C-2' ],
368
+
369
+ [ 'A-1', 'B-2', 'C-3' ],
370
+
371
+ [ 'A-1', 'B-2', 'C-4' ],
372
+
373
+ [ 'A-2', 'B-3', 'C-5' ],
374
+
375
+ [ 'A-2', 'B-3', 'C-6' ],
376
+
377
+ [ 'A-2', 'B-4', 'C-7' ],
378
+
379
+ [ 'A-2', 'B-4', 'C-8' ],
380
+
381
+ [ 'A-1', 'B-5', 'C-9' ],
382
+
383
+ [ 'A-2', 'B-2', 'C-10' ]
384
+
385
+ ]
386
+
387
+ ```
388
+
389
+ というものですが、これのデータ行の3行目 `[ 'A-1', 'B-2', 'C-3' ]` を、ツリー末端の子(葉)のほうから親のほうへ向かうパスとして読むと
390
+
391
+
392
+
393
+ - C-3 の親は B-2 で、B-2 の親は A-1
394
+
395
+
396
+
397
+ と読めるのですが、そうすると、最後の行の `[ 'A-2', 'B-2', 'C-10' ]` は
398
+
399
+
400
+
401
+ - C-10 の親は B-2 で、B-2 の親は A-2
402
+
403
+
404
+
405
+ となってしまい、B-2 には、二つの親、A-1 と A-2 があることになってしまいます。ですが、先のstackoverflow の投稿では、各ノードの親は、木構造の定義に沿って、(最大で)一個であるようなノードの一次元配列を木構造化するコードでした。これを踏まえて、それでも[ベストアンサー](https://stackoverflow.com/a/18018037) の `function list_to_tree(list)` を使おうとすると、id として A-1やB-2だったりの文字列はそのまま使えず、「A-1 が親のB-1 と、A-2が親のB-2とは、別物である」という考え方を採り入れて、それらに異なる id を設ける必要があり、これはけっこう煩雑な作業となりそうです。

10

テキスト修正

2020/06/20 08:02

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- いろいろなやり方がありそうですが、一例を回答します。以下の二次元配列 `tableData` から目的のJSONを得るコードを挙げます
5
+ いろいろなやり方がありそうですが、一例を回答します。以下の二次元配列 `tableData` から目的のJSONを得るコードを挙げます
6
6
 
7
7
  ```javascript
8
8
 
@@ -34,7 +34,7 @@
34
34
 
35
35
  ```
36
36
 
37
- 上記の配列`tableData`から、階層構造を復元したオブジェクトを作ります。その際に lodash の [_.set](https://lodash.com/docs/#set)を使います。
37
+ 上記の配列`tableData`から、階層構造を復元したオブジェクトを作ります。その際に lodash の [_.set](https://lodash.com/docs/#set) を使います。
38
38
 
39
39
 
40
40
 
@@ -270,7 +270,7 @@
270
270
 
271
271
 
272
272
 
273
- ### 追記
273
+ ### 追記1
274
274
 
275
275
 
276
276
 

9

テキスト修正

2020/06/20 05:12

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -332,7 +332,7 @@
332
332
 
333
333
 
334
334
 
335
- const treeArray = tableData.slice(1).reduce((ary, row) => addRowToTree(ary, row), []);
335
+ const treeArray = tableData.slice(1).reduce((tree, row) => addRowToTree(tree, row), []);
336
336
 
337
337
 
338
338
 

8

テキスト修正

2020/06/20 03:36

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -298,7 +298,7 @@
298
298
 
299
299
  const addRowToTree = (treeArray, row) => {
300
300
 
301
- let ary = treeArray;
301
+ let list = treeArray;
302
302
 
303
303
  for (let i=0; i < row.length; ++ i) {
304
304
 
@@ -306,21 +306,21 @@
306
306
 
307
307
  const key = `列${row[i][0]}`;
308
308
 
309
- let obj = ary.find(e => e[key] === row[i]);
309
+ let obj = list.find(e => e[key] === row[i]);
310
310
 
311
311
  if (!obj) {
312
312
 
313
313
  obj = { [key]: row[i], list: [] };
314
314
 
315
- ary.push(obj);
315
+ list.push(obj);
316
316
 
317
317
  }
318
318
 
319
- ary = obj.list;
319
+ list = obj.list;
320
320
 
321
321
  } else {
322
322
 
323
- ary.push(row[i]);
323
+ list.push(row[i]);
324
324
 
325
325
  }
326
326
 

7

テキスト修正

2020/06/19 20:58

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -296,7 +296,7 @@
296
296
 
297
297
  ```javascript
298
298
 
299
- const addRow = (treeArray, row) => {
299
+ const addRowToTree = (treeArray, row) => {
300
300
 
301
301
  let ary = treeArray;
302
302
 
@@ -332,7 +332,7 @@
332
332
 
333
333
 
334
334
 
335
- const treeArray = tableData.slice(1).reduce((ary, row) => addRow(ary, row), []);
335
+ const treeArray = tableData.slice(1).reduce((ary, row) => addRowToTree(ary, row), []);
336
336
 
337
337
 
338
338
 

6

テキスト修正

2020/06/19 20:51

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -304,7 +304,7 @@
304
304
 
305
305
  if (i < row.length-1) {
306
306
 
307
- const key = `列${row[i][0]}`
307
+ const key = `列${row[i][0]}`;
308
308
 
309
309
  let obj = ary.find(e => e[key] === row[i]);
310
310
 

5

テキスト修正

2020/06/19 20:47

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -283,3 +283,63 @@
283
283
 
284
284
 
285
285
  にいくつか出ています。ご質問にある表データの配列を加工して、上記に投稿されているいずれかの回答コードをベースにした階層化コードを作成する手もあるかもしれません。
286
+
287
+
288
+
289
+ ### 追記2
290
+
291
+
292
+
293
+ オブジェクトを経由しない別案を作成しました。こちらは、どの階層においても、元のテーブルでの出現順にリストされます。
294
+
295
+
296
+
297
+ ```javascript
298
+
299
+ const addRow = (treeArray, row) => {
300
+
301
+ let ary = treeArray;
302
+
303
+ for (let i=0; i < row.length; ++ i) {
304
+
305
+ if (i < row.length-1) {
306
+
307
+ const key = `列${row[i][0]}`
308
+
309
+ let obj = ary.find(e => e[key] === row[i]);
310
+
311
+ if (!obj) {
312
+
313
+ obj = { [key]: row[i], list: [] };
314
+
315
+ ary.push(obj);
316
+
317
+ }
318
+
319
+ ary = obj.list;
320
+
321
+ } else {
322
+
323
+ ary.push(row[i]);
324
+
325
+ }
326
+
327
+ }
328
+
329
+ return treeArray;
330
+
331
+ };
332
+
333
+
334
+
335
+ const treeArray = tableData.slice(1).reduce((ary, row) => addRow(ary, row), []);
336
+
337
+
338
+
339
+ console.log(JSON.stringify(treeArray, null, 2));
340
+
341
+ ```
342
+
343
+
344
+
345
+ - **動作確認用CodePen:** [https://codepen.io/jun68ykt/pen/oNbBaKE?editors=0012](https://codepen.io/jun68ykt/pen/oNbBaKE?editors=0012)

4

テキスト修正

2020/06/19 20:43

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -108,56 +108,30 @@
108
108
 
109
109
  ```
110
110
 
111
- この`treeObj` から、目的の配列を得るための再帰関数 `treeObjToArray` と、これの中で使うソート用の比較関数 `keyCompare` を作成します。
111
+ この`treeObj` から、目的の配列を得るための再帰関数 `treeObjToArray` を作成します。
112
-
113
-
114
-
112
+
113
+
114
+
115
- ```javascript
115
+ ```javascript
116
-
116
+
117
- const keyCompare = (k1, k2) => {
117
+ const treeObjToArray = obj => {
118
-
119
- const ch1 = k1[0], ch2 = k2[0];
118
+
120
-
121
- const n1 = +k1.substring(2), n2 = +k2.substring(2);
119
+ const entries = Object.entries(obj).sort(([k1], [k2]) => k1.substring(2) - k2.substring(2));
122
-
120
+
123
- return ch1 !== ch2 ? ch1.localeCompare(ch2) : n1 - n2;
121
+ return entries.map(([k, v]) => ({
122
+
123
+ [`列${k[0]}`]: k,
124
+
125
+ list: Object.values(v)[0] ?
126
+
127
+ treeObjToArray(v) : Object.keys(v).sort((k1, k2) => k1.substring(2) - k2.substring(2))
128
+
129
+ })
130
+
131
+ );
124
132
 
125
133
  }
126
134
 
127
-
128
-
129
- ```
130
-
131
- 上記の `keyCompare` は、セルの文字列を以下のように順序づけます。
132
-
133
-
134
-
135
- `A-1` < `A-2` < `B-2` < `B-10` < `C-1`
136
-
137
-
138
-
139
- `treeObj` から、目的の配列を得るための再帰関数 `treeObjToArray`は以下です。
140
-
141
- ```javascript
142
-
143
- const treeObjToArray = obj => {
144
-
145
- const entries = Object.entries(obj).sort(([k1], [k2]) => keyCompare(k1, k2));
146
-
147
- return entries.map(([k, v]) => ({
148
-
149
- [`列${k[0]}`]: k,
150
-
151
- list: Object.values(v)[0] ?
152
-
153
- treeObjToArray(v) : Object.keys(v).sort((k1, k2) => keyCompare(k1, k2))
154
-
155
- })
156
-
157
- );
158
-
159
- }
160
-
161
135
  ```
162
136
 
163
137
  上記の`treeObjToArray` に `treeObj` を与えて、目的の配列 `treeArray` を得ます。
@@ -286,7 +260,7 @@
286
260
 
287
261
 
288
262
 
289
- - **動作確認用CodePen:** [https://codepen.io/jun68ykt/pen/wvMgYMX?editors=0012](https://codepen.io/jun68ykt/pen/wvMgYMX?editors=0012)
263
+ - **動作確認用CodePen:** [https://codepen.io/jun68ykt/pen/KKVaGXj?editors=0012](https://codepen.io/jun68ykt/pen/KKVaGXj?editors=0012)
290
264
 
291
265
 
292
266
 

3

テキスト修正

2020/06/19 19:27

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
  ```javascript
42
42
 
43
- const treeObj = tableData.slice(1).reduce((o, path) => _(o).set(path, null).value(), {});
43
+ const treeObj = tableData.slice(1).reduce((obj, path) => _(obj).set(path, null).value(), {});
44
44
 
45
45
  ```
46
46
 

2

テキスト修正

2020/06/19 19:18

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -2,335 +2,291 @@
2
2
 
3
3
 
4
4
 
5
- いろいろなやり方がありそうですが、一例を挙げておきます
6
-
7
-
8
-
9
- この回答では、以下のような、空白文字で区切られたテキストとして与えられた表データから、目的のJSONを得るコードを挙げます。
10
-
11
-
12
-
13
- ```javascript
14
-
15
- const tableText =
16
-
17
- `列A B C
18
-
19
- A-1 B-1 C-1
20
-
21
- A-1 B-1 C-2
22
-
23
- A-1 B-2 C-3
24
-
25
- A-1 B-2 C-4
26
-
27
- A-2 B-3 C-5
28
-
29
- A-2 B-3 C-6
30
-
31
- A-2 B-4 C-7
32
-
33
- A-2 B-4 C-8
34
-
35
- A-1 B-5 C-9
36
-
37
- A-2 B-2 C-10`;
38
-
39
- ```
40
-
41
-
42
-
43
- 以下によって、各セルの値の配列を得ます。
44
-
45
- ```javascript
46
-
47
- const tableData = tableText.split('\n').map(str => str.trim().split(/\s+/)).splice(1);
48
-
49
- ```
50
-
51
- 上記によって、 `tableData` は、以下のような二次元配列になります。
52
-
53
- ```javascript
5
+ いろいろなやり方がありそうですが、一例を回答します。以下の二次元配列 `tableData` から目的のJSONを得るコードを挙げます
6
+
7
+ ```javascript
8
+
9
+ const tableData = [
10
+
11
+ [ '列A', '列B', '列C' ],
12
+
13
+ [ 'A-1', 'B-1', 'C-1' ],
14
+
15
+ [ 'A-1', 'B-1', 'C-2' ],
16
+
17
+ [ 'A-1', 'B-2', 'C-3' ],
18
+
19
+ [ 'A-1', 'B-2', 'C-4' ],
20
+
21
+ [ 'A-2', 'B-3', 'C-5' ],
22
+
23
+ [ 'A-2', 'B-3', 'C-6' ],
24
+
25
+ [ 'A-2', 'B-4', 'C-7' ],
26
+
27
+ [ 'A-2', 'B-4', 'C-8' ],
28
+
29
+ [ 'A-1', 'B-5', 'C-9' ],
30
+
31
+ [ 'A-2', 'B-2', 'C-10' ]
32
+
33
+ ];
34
+
35
+ ```
36
+
37
+ 上記の配列`tableData`から、階層構造を復元したオブジェクトを作ります。その際に lodash [_.set](https://lodash.com/docs/#set)を使います。
38
+
39
+
40
+
41
+ ```javascript
42
+
43
+ const treeObj = tableData.slice(1).reduce((o, path) => _(o).set(path, null).value(), {});
44
+
45
+ ```
46
+
47
+ 上記によって、`treeObj` に下記のようなオブジェクトが得られます。
48
+
49
+
50
+
51
+ ```javascript
52
+
53
+ {
54
+
55
+ "A-1": {
56
+
57
+ "B-1": {
58
+
59
+ "C-1": null,
60
+
61
+ "C-2": null
62
+
63
+ },
64
+
65
+ "B-2": {
66
+
67
+ "C-3": null,
68
+
69
+ "C-4": null
70
+
71
+ },
72
+
73
+ "B-5": {
74
+
75
+ "C-9": null
76
+
77
+ }
78
+
79
+ },
80
+
81
+ "A-2": {
82
+
83
+ "B-3": {
84
+
85
+ "C-5": null,
86
+
87
+ "C-6": null
88
+
89
+ },
90
+
91
+ "B-4": {
92
+
93
+ "C-7": null,
94
+
95
+ "C-8": null
96
+
97
+ },
98
+
99
+ "B-2": {
100
+
101
+ "C-10": null
102
+
103
+ }
104
+
105
+ }
106
+
107
+ }
108
+
109
+ ```
110
+
111
+ この`treeObj` から、目的の配列を得るための再帰関数 `treeObjToArray` と、これの中で使うソート用の比較関数 `keyCompare` を作成します。
112
+
113
+
114
+
115
+ ```javascript
116
+
117
+ const keyCompare = (k1, k2) => {
118
+
119
+ const ch1 = k1[0], ch2 = k2[0];
120
+
121
+ const n1 = +k1.substring(2), n2 = +k2.substring(2);
122
+
123
+ return ch1 !== ch2 ? ch1.localeCompare(ch2) : n1 - n2;
124
+
125
+ }
126
+
127
+
128
+
129
+ ```
130
+
131
+ 上記の `keyCompare` は、セルの文字列を以下のように順序づけます。
132
+
133
+
134
+
135
+ `A-1` < `A-2` < `B-2` < `B-10` < `C-1`
136
+
137
+
138
+
139
+ `treeObj` から、目的の配列を得るための再帰関数 `treeObjToArray`は以下です。
140
+
141
+ ```javascript
142
+
143
+ const treeObjToArray = obj => {
144
+
145
+ const entries = Object.entries(obj).sort(([k1], [k2]) => keyCompare(k1, k2));
146
+
147
+ return entries.map(([k, v]) => ({
148
+
149
+ [`列${k[0]}`]: k,
150
+
151
+ list: Object.values(v)[0] ?
152
+
153
+ treeObjToArray(v) : Object.keys(v).sort((k1, k2) => keyCompare(k1, k2))
154
+
155
+ })
156
+
157
+ );
158
+
159
+ }
160
+
161
+ ```
162
+
163
+ 上記の`treeObjToArray` に `treeObj` を与えて、目的の配列 `treeArray` を得ます。
164
+
165
+ ```javascript
166
+
167
+ const treeArray = treeObjToArray(treeObj);
168
+
169
+
170
+
171
+ console.log(JSON.stringify(treeArray, null, 2));
172
+
173
+ ```
174
+
175
+ 上記によって、以下が出力されます。
176
+
177
+
178
+
179
+ ```json
54
180
 
55
181
  [
56
182
 
183
+ {
184
+
185
+ "列A": "A-1",
186
+
187
+ "list": [
188
+
189
+ {
190
+
57
- [ 'A-1', 'B-1', 'C-1' ],
191
+ "列B": "B-1",
192
+
58
-
193
+ "list": [
194
+
195
+ "C-1",
196
+
197
+ "C-2"
198
+
199
+ ]
200
+
201
+ },
202
+
203
+ {
204
+
59
- [ 'A-1', 'B-1', 'C-2' ],
205
+ "列B": "B-2",
206
+
60
-
207
+ "list": [
208
+
209
+ "C-3",
210
+
211
+ "C-4"
212
+
213
+ ]
214
+
215
+ },
216
+
217
+ {
218
+
219
+ "列B": "B-5",
220
+
221
+ "list": [
222
+
223
+ "C-9"
224
+
225
+ ]
226
+
227
+ }
228
+
229
+ ]
230
+
231
+ },
232
+
233
+ {
234
+
235
+ "列A": "A-2",
236
+
237
+ "list": [
238
+
239
+ {
240
+
61
- [ 'A-1', 'B-2', 'C-3' ],
241
+ "列B": "B-2",
242
+
62
-
243
+ "list": [
244
+
245
+ "C-10"
246
+
247
+ ]
248
+
249
+ },
250
+
251
+ {
252
+
253
+ "列B": "B-3",
254
+
255
+ "list": [
256
+
257
+ "C-5",
258
+
259
+ "C-6"
260
+
261
+ ]
262
+
263
+ },
264
+
265
+ {
266
+
63
- [ 'A-1', 'B-2', 'C-4' ],
267
+ "列B": "B-4",
64
-
268
+
65
- [ 'A-2', 'B-3', 'C-5' ],
269
+ "list": [
66
-
67
- [ 'A-2', 'B-3', 'C-6' ],
270
+
68
-
69
- [ 'A-2', 'B-4', 'C-7' ],
271
+ "C-7",
70
-
272
+
71
- [ 'A-2', 'B-4', 'C-8' ],
273
+ "C-8"
72
-
274
+
73
- [ 'A-1', 'B-5', 'C-9' ],
275
+ ]
276
+
74
-
277
+ }
278
+
75
- [ 'A-2', 'B-2', 'C-10' ]
279
+ ]
280
+
281
+ }
76
282
 
77
283
  ]
78
284
 
79
285
  ```
80
286
 
81
- 上記の配列`tableData`から、階層構造を復元したオブジェクトを作ります。その際に lodash の [_.set](https://lodash.com/docs/#set)を使います。
287
+
82
-
83
-
84
-
85
- ```javascript
288
+
86
-
87
- const treeObj = tableData.reduce((o, path) => _(o).set(path, null).value(), {});
88
-
89
- ```
90
-
91
- 上記によって、`treeObj` に下記のようなオブジェクトが得られます。
92
-
93
-
94
-
95
- ```javascript
96
-
97
- {
98
-
99
- "A-1": {
100
-
101
- "B-1": {
102
-
103
- "C-1": null,
104
-
105
- "C-2": null
106
-
107
- },
108
-
109
- "B-2": {
110
-
111
- "C-3": null,
112
-
113
- "C-4": null
114
-
115
- },
116
-
117
- "B-5": {
118
-
119
- "C-9": null
120
-
121
- }
122
-
123
- },
124
-
125
- "A-2": {
126
-
127
- "B-3": {
128
-
129
- "C-5": null,
130
-
131
- "C-6": null
132
-
133
- },
134
-
135
- "B-4": {
136
-
137
- "C-7": null,
138
-
139
- "C-8": null
140
-
141
- },
142
-
143
- "B-2": {
144
-
145
- "C-10": null
146
-
147
- }
148
-
149
- }
150
-
151
- }
152
-
153
- ```
154
-
155
- この`treeObj` から、目的の配列を得るための再帰関数 `treeObjToArray` と、これの中で使うソート用の比較関数 `keyCompare` を作成します。
156
-
157
-
158
-
159
- ```javascript
160
-
161
- const keyCompare = (k1, k2) => {
162
-
163
- const ch1 = k1[0], ch2 = k2[0];
164
-
165
- const n1 = +k1.substring(2), n2 = +k2.substring(2);
166
-
167
- return ch1 !== ch2 ? ch1.localeCompare(ch2) : n1 - n2;
168
-
169
- }
170
-
171
-
172
-
173
- ```
174
-
175
- 上記の `keyCompare` は、セルの文字列を以下のように順序づけます。
176
-
177
-
178
-
179
- `A-1` < `A-2` < `B-2` < `B-10` < `C-1`
180
-
181
-
182
-
183
- `treeObj` から、目的の配列を得るための再帰関数 `treeObjToArray`は以下です。
184
-
185
- ```javascript
186
-
187
- const treeObjToArray = obj => {
188
-
189
- const entries = Object.entries(obj).sort(([k1], [k2]) => keyCompare(k1, k2));
190
-
191
- return entries.map(([k, v]) => ({
192
-
193
- [`列${k[0]}`]: k,
194
-
195
- list: Object.values(v)[0] ?
196
-
197
- treeObjToArray(v) : Object.keys(v).sort((k1, k2) => keyCompare(k1, k2))
198
-
199
- })
200
-
201
- );
202
-
203
- }
204
-
205
- ```
206
-
207
- 上記の`treeObjToArray` に `treeObj` を与えて、目的の配列 `treeArray` を得ます。
208
-
209
- ```javascript
210
-
211
- const treeArray = treeObjToArray(treeObj);
212
-
213
-
214
-
215
- console.log(JSON.stringify(treeArray, null, 2));
216
-
217
- ```
218
-
219
- 上記によって、以下が出力されます。
220
-
221
-
222
-
223
- ```json
224
-
225
- [
226
-
227
- {
228
-
229
- "列A": "A-1",
230
-
231
- "list": [
232
-
233
- {
234
-
235
- "列B": "B-1",
236
-
237
- "list": [
238
-
239
- "C-1",
240
-
241
- "C-2"
242
-
243
- ]
244
-
245
- },
246
-
247
- {
248
-
249
- "列B": "B-2",
250
-
251
- "list": [
252
-
253
- "C-3",
254
-
255
- "C-4"
256
-
257
- ]
258
-
259
- },
260
-
261
- {
262
-
263
- "列B": "B-5",
264
-
265
- "list": [
266
-
267
- "C-9"
268
-
269
- ]
270
-
271
- }
272
-
273
- ]
274
-
275
- },
276
-
277
- {
278
-
279
- "列A": "A-2",
280
-
281
- "list": [
282
-
283
- {
284
-
285
- "列B": "B-2",
286
-
287
- "list": [
288
-
289
- "C-10"
290
-
291
- ]
292
-
293
- },
294
-
295
- {
296
-
297
- "列B": "B-3",
298
-
299
- "list": [
300
-
301
- "C-5",
302
-
303
- "C-6"
304
-
305
- ]
306
-
307
- },
308
-
309
- {
310
-
311
- "列B": "B-4",
312
-
313
- "list": [
314
-
315
- "C-7",
316
-
317
- "C-8"
318
-
319
- ]
320
-
321
- }
322
-
323
- ]
324
-
325
- }
326
-
327
- ]
328
-
329
- ```
330
-
331
-
332
-
333
- - **動作確認用CodePen:** [https://codepen.io/jun68ykt/pen/JjGEBgx?editors=0012](https://codepen.io/jun68ykt/pen/JjGEBgx?editors=0012)
289
+ - **動作確認用CodePen:** [https://codepen.io/jun68ykt/pen/wvMgYMX?editors=0012](https://codepen.io/jun68ykt/pen/wvMgYMX?editors=0012)
334
290
 
335
291
 
336
292
 

1

テキスト修正

2020/06/19 19:03

投稿

jun68ykt
jun68ykt

スコア9058

test CHANGED
@@ -176,9 +176,7 @@
176
176
 
177
177
 
178
178
 
179
- `A-1` < `A-2` < `B-1` < `B-10` < `C-1`
179
+ `A-1` < `A-2` < `B-2` < `B-10` < `C-1`
180
-
181
-
182
180
 
183
181
 
184
182
 
@@ -337,3 +335,21 @@
337
335
 
338
336
 
339
337
  以上参考になれば幸いです。
338
+
339
+
340
+
341
+
342
+
343
+ ### 追記
344
+
345
+
346
+
347
+ 別案を検討する際の参考情報です。一次元のオブジェクト配列から、オブジェクト間の階層構造を復元した配列に変換するコードの例は
348
+
349
+
350
+
351
+ - stackoverflow [Build tree array from flat array in javascript](https://stackoverflow.com/questions/18017869)
352
+
353
+
354
+
355
+ にいくつか出ています。ご質問にある表データの配列を加工して、上記に投稿されているいずれかの回答コードをベースにした階層化コードを作成する手もあるかもしれません。