回答編集履歴
3
補足説明追加
answer
CHANGED
@@ -76,6 +76,7 @@
|
|
76
76
|
[JavaScript の配列のシャローコピーに使えるメソッド3つ(+ 1つ)とその使い分け - おかかウェブ](http://okakacacao.wpblog.jp/technology/javascript-array-shallow-copy)
|
77
77
|
|
78
78
|
回答文に上がっている解決策はこのシャローコピーやディープコピーの手法です。
|
79
|
+
(この手法はどちらもちゃんとGASで使える事を確認しています)
|
79
80
|
|
80
81
|
- `JSON.parse(JSON.stringify(...))`: 簡易的なディープコピー
|
81
82
|
- `array.slice()`: スマートなシャローコピー
|
@@ -85,7 +86,7 @@
|
|
85
86
|
【おまけ】【修正版】関数作ってワンライナーで頑張る
|
86
87
|
|
87
88
|
一撃で行けると思ったのですが、どうもGASはJavaScript1.6ベースでできており、
|
88
|
-
|
89
|
+
ECMAScript6の便利機能は全滅、5も動作が怪しいので、注意してください。
|
89
90
|
|
90
91
|
参考サイト
|
91
92
|
|
@@ -95,6 +96,7 @@
|
|
95
96
|
|
96
97
|
そもそも配列の要素を一気につくるイディオムがES6に頼る事になるので、
|
97
98
|
それに頼れないとなると一気に微妙化しますが、こんな感じで配列作る関数を用意して動作させることになります。
|
99
|
+
下記のコードは調査済みで動作します…が、`array.slice()`の方が明らかに筋が良いですね。参考までにどうぞ。
|
98
100
|
|
99
101
|
```JavaScript
|
100
102
|
function myFunction() {
|
2
回避策を記載
answer
CHANGED
@@ -82,19 +82,33 @@
|
|
82
82
|
|
83
83
|
---
|
84
84
|
|
85
|
-
【おまけ】
|
86
|
-
ま
|
85
|
+
【おまけ】【修正版】関数作ってワンライナーで頑張る
|
87
86
|
|
88
|
-
```
|
89
|
-
n = 11;
|
90
|
-
|
87
|
+
一撃で行けると思ったのですが、どうもGASはJavaScript1.6ベースでできており、
|
91
|
-
|
88
|
+
ECMAScript5や6の便利機能はほぼ使えないようです。
|
92
|
-
// (11) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
93
|
-
var maze = Array(n).fill(0).map(() => Array(n).fill(0));
|
94
|
-
console.log(maze);
|
95
|
-
// (11) [Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11)]
|
96
|
-
```
|
97
89
|
|
98
|
-
|
99
|
-
|
100
|
-
|
90
|
+
参考サイト
|
91
|
+
|
92
|
+
- [What functions do Arrays in Google Apps Script support?](https://stackoverflow.com/questions/39317252/what-functions-do-arrays-in-google-apps-script-support)
|
93
|
+
- [Basic JavaScript features](https://developers.google.com/apps-script/guides/services/#basic_javascript_features)
|
94
|
+
- [JavaScript 1.6 の新機能 - MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/New_in_JavaScript/1.6)
|
95
|
+
|
96
|
+
そもそも配列の要素を一気につくるイディオムがES6に頼る事になるので、
|
97
|
+
それに頼れないとなると一気に微妙化しますが、こんな感じで配列作る関数を用意して動作させることになります。
|
98
|
+
|
99
|
+
```JavaScript
|
100
|
+
function myFunction() {
|
101
|
+
var n = 11;
|
102
|
+
var array = function (num) {
|
103
|
+
var arr = [];
|
104
|
+
for (var i = 0; i < num; i++) {
|
105
|
+
arr.push(0);
|
106
|
+
}
|
107
|
+
return arr;
|
108
|
+
}
|
109
|
+
var maze = array(n).map(function () { return array(n); });
|
110
|
+
Logger.log(maze);
|
111
|
+
}
|
112
|
+
|
113
|
+
// [18-12-07 17:36:31:549 JST] [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]
|
114
|
+
```
|
1
おまけ追加
answer
CHANGED
@@ -14,9 +14,13 @@
|
|
14
14
|
|
15
15
|
---
|
16
16
|
|
17
|
-
JavaScriptの世界では、`{name: "hoge"}`というオブジェクトや、`[1, 2, 3]`という配列を
|
17
|
+
JavaScriptの世界では、`{name: "hoge"}`というオブジェクトや、`[1, 2, 3]`という配列を宣言した時、初めてメモリ空間上にオブジェクト/配列が生成されます。
|
18
|
+
変数や引数として使う時は全て「メモリ空間のアドレス番地」でやりとりされます(参照やポインタ等と表現されます)
|
19
|
+
変数に代入された時、目には見えませんしとりだせませんが、オブジェクト/配列の実体ではなく、アドレス番地という数値が代入されていると考えてください。
|
20
|
+
|
18
21
|
`[1, 2, 3] === [1, 2, 3]`の結果が`false`になるのは、比較演算子でオブジェクトや配列を比較した場合、配列そのものではなく、「アドレス番地」での比較になります。
|
22
|
+
1行内に配列宣言が2個ありますので、メモリ空間上に配列2個作られ、それぞれのアドレス番地が帰って来ます。
|
19
|
-
|
23
|
+
各々のアドレス番地は当然異なる為、比較結果も`false`になるというカラクリになっています。
|
20
24
|
|
21
25
|
これがどう質問文に影響してくるかを見ていきましょう。
|
22
26
|
|
@@ -42,10 +46,30 @@
|
|
42
46
|
`maze.push(array)`としていますが、arrayには配列のアドレス番地が入ってます。
|
43
47
|
つまり、11回繰り返した結果mazeは`[arrayのアドレス番地, arrayのアドレス番地, arrayのアドレス番地, ...]`という配列になります。
|
44
48
|
|
45
|
-
|
49
|
+
理想はメモリ空間上にmazeとarrayのコピー11個、計12個の配列が存在して`maze`の中身は`[array1, array2, array3 ...]`という風になって欲しいはずですが、
|
46
|
-
実際にはmazeと
|
50
|
+
実際にはmazeとarrayの計2個の配列しか存在していません。
|
51
|
+
そりゃarrayの値を1個弄ったら全部変化するよね……という訳で、そのコードは欠陥となるわけです。
|
47
52
|
|
53
|
+
配列は基本的に宣言したタイミングで作られるので、
|
54
|
+
素直に解決するなら多重ループに変更してこういったコードになるでしょう。
|
55
|
+
|
56
|
+
```JavaScript
|
57
|
+
function main (n) {
|
58
|
+
n = 11;
|
59
|
+
var maze = [];
|
60
|
+
for (var i = 0; i < n; i++) {
|
61
|
+
// ループの中で新しい配列を作って育てる
|
62
|
+
var array = [];
|
63
|
+
for (var j = 0; j < n; j++) {
|
64
|
+
array.push(0);
|
65
|
+
}
|
66
|
+
maze.push(array);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
ですが、ループやif文のネストって理解が難しくなるのでできれば避けたいですよね。
|
48
|
-
|
72
|
+
そういった時に、メモリ空間上に配列の複製を作ってしまう手法があり、
|
49
73
|
これをシャローコピーやディープコピーと呼びます。
|
50
74
|
詳しい記事を見つけたので、具体的な方法はこちらを読んでみてください。
|
51
75
|
|
@@ -54,4 +78,23 @@
|
|
54
78
|
回答文に上がっている解決策はこのシャローコピーやディープコピーの手法です。
|
55
79
|
|
56
80
|
- `JSON.parse(JSON.stringify(...))`: 簡易的なディープコピー
|
57
|
-
- `array.slice()`: スマートなシャローコピー
|
81
|
+
- `array.slice()`: スマートなシャローコピー
|
82
|
+
|
83
|
+
---
|
84
|
+
|
85
|
+
【おまけ】
|
86
|
+
まぁ、n個の要素を持つ配列ならイディオム覚えれば1行ですね。
|
87
|
+
|
88
|
+
```
|
89
|
+
n = 11;
|
90
|
+
// 全て0埋めしたn個の配列
|
91
|
+
console.log(Array(n).fill(0));
|
92
|
+
// (11) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
93
|
+
var maze = Array(n).fill(0).map(() => Array(n).fill(0));
|
94
|
+
console.log(maze);
|
95
|
+
// (11) [Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11), Array(11)]
|
96
|
+
```
|
97
|
+
|
98
|
+
`Array(n).fill(0)`自体が0埋めされたn個の配列を新しく作るというイディオムであり、
|
99
|
+
[Array.prototype.map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)は冒頭に「その結果からなる新しい配列を生成します。」と書いてあるように、
|
100
|
+
新しい配列を作っているので質問文の問題は解消された状態になっています。
|