67363


# 理解していること

## 配列

セルに

[code]

    ={2,4,6}
    
[/code]

を入力すると横に展開されて（？正しい日本語の表現がわからないので知っていたら教えて下さい）以下のようになります。

[![画像の説明をここに入力](https://i.stack.imgur.com/GK6PU.png)](https://i.stack.imgur.com/GK6PU.png)

同様にセルに

[code]

    ={2;4;6}
    
[/code]

と入力すると、今度は縦に展開（？）される。

このような機能を「配列」という。

## ARRAYFORMULA

1から100までの配列を `={1; 2; 3; ....}` と打つのはあまりにも手間すぎるので

[code]

    =ARRAYFORMULA((ROW(A1:A100)))
    
[/code]

と書ける。

私が理解していることは上記です。

# 質問

下記のようなスプレッドシートを用意してみました。

[![画像の説明をここに入力](https://i.stack.imgur.com/hgcN3.png)](https://i.stack.imgur.com/hgcN3.png)

A列もB列にも 1から10までの値を入れています。  
そしてセルC1に

[code]

    =ARRAYFORMULA(A1:A10*B1:B10)
    
[/code]

を書くと、隣り合ったセル同士を掛けた内容が出力されました。

セル同士を掛けた（正確にはセルの **範囲** 同士を掛けた？） `A1:A10*B1:B10` はどういう意味なのでしょうか？ もしくは
`A1:A10*B1:B10`
自体にはまだ意味がなく、`ARRAYFORMULA`に渡した時点で意味を持つのであれば、`ARRAYFORMULA(A1:A10*B1:B10)`はどういう意味なのか教えて下さい（どういうことが起こるのかはわかっているので、なぜこうなるのかを教えて下さい）。

# 参考

  * [【保存版】スプレッドシートで配列や行列を作成する方法まとめ | たぬハック](https://tanuhack.com/array-matrix-creation/)

* * *

# 追記

## 理解していること

  * [スプレッドシートの『ARRAYFORMULA』関数を使って表示速度を高速化させよう！ | たぬハック](https://tanuhack.com/spreadsheets-arrayformula/)

を見ると、数式を **範囲化する魔法をかける** のが`ARRAYFORMULA`のようですね。

本来は `A1*B1` としかできないのを、`*`に範囲化魔法を掛けて`A1:A10*B1:B10` とできるようにしたということですね。

## 質問

うーん。しかし範囲化させるルールがよくわからないです。どうしていい感じに隣同士が掛け合わされるのか。そして、`ARRAYFORMULA`を書いたセルの下に順々に計算結果が表示されたのでしょうか？
下ではなくて、右に展開されてもおかしくないような気もします。

たとえば九九の表を作るときに`ARRAYFORMULA`を使わないのであれば、

[![画像の説明をここに入力](https://i.stack.imgur.com/bVWh0.png)](https://i.stack.imgur.com/bVWh0.png)

[code]

    =$A2*B$1
    
[/code]

というように、フィルハンドルで伸ばしたときに、どこを固定させるか神経質に考えないといけませんが、`ARRAYFORMULA`であれば、下記のように

[code]

    =ARRAYFORMULA(A2:A10*B1:J1)
    
[/code]

で済んでしまいます。

[![画像の説明をここに入力](https://i.stack.imgur.com/eXLqN.png)](https://i.stack.imgur.com/eXLqN.png)

この場合、右にも下にもいい感じに展開されてますが、展開ルールがわかりません。


CC BY-SA 4.0
2020-06-05T11:51:12.610
67332
2020-06-07T06:52:20.703
2020-06-06T01:57:48.547
9008
9008
question
google-spreadsheet
ARRAYFORMULAの展開ルールがわかりません


範囲の組み合わせを全部生成して、`lhs`と`rhs`をオペレーターで計算して結果を該当するセルに挿入すると考えると理解しやすいかと思います。

`ARRAYFORMULA(A1:A10*B1:B10)`は引数の`lhs`と`rhs`の行成分が同一なので、列（間違いではありません）成分を一回、行成分を1~10まで生成し、A1*B1,
A2*B2,...A10*B10という配列を生成し、スプレッドシートに配列を貼り付けます

[code]

    // lhs, rhs は該当するセルの値(left/right hand sideの略で、オペレーター(+-*/等)の左右要素を示すのに良く使う略語)
    // offsetRow, offsetCol は0から始まる、lhs, rhsの順番
    // cellValue は便宜的に、列、行を引数に該当するセルの値を取り出す関数
    lhsAnchor = A
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].each { |lhs, offsetRow|
        [B].each { |rhs, offsetCol|
            lhsValue = cellValue(lhsAnchor, lhs)
            rhsValue = cellValue(rhs, lhs)
            ans = lhsValue * rhsValue
            ansArray[offsetRow][offsetCol] = ans
        }
    }
    
[/code]

で、内側のループが一回なので、一次元の配列になると見なせ、スプレッドシートに貼り付けられるのはこの場合は同じ列の複数行にわたる値と見なせます。

同様に、`ARRAYFORMULA(A2:A10*B1:J1)`は、引数の`lhs`で行成分が2~10の9回、`rhs`で列成分がB~Jの9回繰り返し、2重ループが生成され、結果として、行と列の2次元配列が生成され、スプレッドシートに貼り付けられます。  
仮想言語的にこのループを表現すると

[code]

    lhsAnchor = A
    rhsAnchor = 2
    [2, 3, 4, 5, 6, 7, 8, 9, 10].each { |lhs, offsetRow|
        [B, C, D, E, F, G, H, I, J].each { |rhs, offsetCol|
            lhsValue = cellValue(lhsAnchor, lhs)
            rhsValue = cellValue(rhs, rhsAnchor)
            ans = lhsValue * rhsValue
            ansArray[offsetRow][offsetCol] = ans
        }
    }
    
[/code]

となり、上の仮想言語での`ansArray`は2次元配列になるので、スプレッドシートに貼り付けられる値の範囲も列と行成分を持つ2次元の領域になります。


CC BY-SA 4.0
2020-06-06T10:42:00.293
67363
2020-06-07T06:52:20.703
2020-06-07T06:52:20.703
9008
14745
67332
answer