VBAユーザがPython・Rを使ってみた：繰り返し処理

# はじめに

機械学習の勉強を始めたVBAユーザです。
備忘録としてPython・Rの文法をVBAと比較しながらまとめていきたいと思います。


**目次**

- [繰り返し処理](#繰り返し処理)
   - [for文](#for文)
      - [シンプルな例](#シンプルな例)
      - [他の例](#他の例)
      - [さらに](#さらに)
   - [while文](#while文)
   - [ループの終了](#ループの終了)
   - [ループのスキップ](#ループのスキップ)
   - [その他](#その他)
- [まとめ](#まとめ)
   - [一覧](#一覧)
   - [プログラム全体](#プログラム全体)


# 繰り返し処理
今回は、繰り返し処理（ループ処理）についてまとめます。

## for文
まずは、for文です。

### シンプルな例
シンプルなfor文の例です。

**Python**

```Python:Python3
# for文
for i in range(5):
    print(i)
# 0
# 1
# 2
# 3
# 4
print(range(5))       # range(0, 5)
print(type(range(5))) # <class 'range'>
print(list(range(5))) # [0, 1, 2, 3, 4]
```
Pythonではfor文のブロックをインデント（字下げ）で表現します。
`range(5)`は 0,1,2,3,4 という整数を順番に返すイテラブルオブジェクト(iterable object)（反復可能オブジェクト）で、`list(range(5))` でリスト`[0, 1, 2, 3, 4]` になります。

**R**

```R:R
for (i in 0:4) {
  print(i)
}
# [1] 0
# [1] 1
# [1] 2
# [1] 3
# [1] 4
print(0:4)   # 0 1 2 3 4
```
`0:4`は 0 から 4 までの整数値のベクトルです。

**VBA**

```VBA:VBA
For i = 0 To 4
    Debug.Print i
Next i
' 0
' 1
' 2
' 3
' 4
```


### 他の例

**Python**

```Python:Python3
Ns = [2, 3, 5, 7, 11]
for i in range(len(Ns)):
    print(Ns[i])
# 2
# 3
# 5
# 7
# 11

Ns = [2, 3, 5, 7, 11]
for n in Ns:
    print(n)
# 2
# 3
# 5
# 7
# 11
```
Pythonでは、リストもイテラブルオブジェクトなので、`in`の後に指定できます。

**R**

```R:R
Ns <- c(2, 3, 5, 7, 11)
for (i in 1:length(Ns)) {
  print(Ns[i])
}
# [1] 2
# [1] 3
# [1] 5
# [1] 7
# [1] 11

Ns <- c(2, 3, 5, 7, 11)
for (n in Ns) {
  print(n)
}
# [1] 2
# [1] 3
# [1] 5
# [1] 7
# [1] 11
```
Rでも、`in`の後にベクトルを指定できます。

**VBA**

```VBA:VBA
A = Array(2, 3, 5, 7, 11)
For i = LBound(A) To UBound(A)
    Debug.Print A(i)
Next i
' 2
' 3
' 5
' 7
' 11
```
VBAで、`A = Array(2, 3, 5, 7, 11)` と書くと、配列Aのインデックスは（デフォルトの設定では）0から4の整数になります。`LBound(A)`は配列Aの最小のインデックス（ここでは0）、`UBound(A)`は配列Aの最大のインデックス（ここでは4）を返します。


### さらに
Pythonではこのような書き方もできます。

***enumerate関数***
enumerate関数は、イテラブルオブジェクトに対して`(要素番号, 要素)` の形のタプルを１つずつ返すイテラブルオブジェクトを返す組み込み関数です。

**Python**

```Python:Python3
Ns = [2, 3, 5, 7, 11]
for i, n in enumerate(Ns):
    print('Ns[' + str(i) + '] = ' + str(n))
# Ns[0] = 2
# Ns[1] = 3
# Ns[2] = 5
# Ns[3] = 7
# Ns[4] = 11

Ns = [2, 3, 5, 7, 11]
for i, n in enumerate(Ns):
    print('Ns[{}] = {}'.format(i, n))
# Ns[0] = 2
# Ns[1] = 3
# Ns[2] = 5
# Ns[3] = 7
# Ns[4] = 11
```

同じことをRとVBAで書くならこうなります。
**R**

```R:R
Ns <- c(2, 3, 5, 7, 11)
for (i in 1:length(Ns)) {
  n = Ns[i]
  cat(paste0("Ns[", i, "] = ", n, "\n"))
}
# Ns[1] = 2
# Ns[2] = 3
# Ns[3] = 5
# Ns[4] = 7
# Ns[5] = 11
```

**VBA**

```VBA:VBA
A = Array(2, 3, 5, 7, 11)
For i = LBound(A) To UBound(A)
    Debug.Print "Ns[" & CStr(i) & "] = " & Str(A(i))
Next i
' Ns [0] = 2
' Ns [1] = 3
' Ns [2] = 5
' Ns [3] = 7
' Ns [4] = 11
```


***zip関数***
zip関数は、複数のイテラブルオブジェクトに対してそれぞれからの要素のペアを１つずつ返すイテラブルオブジェクトを返す組み込み関数です。

**Python**

```Python:Python3
numbers = list(range(5))
alphabets = 'abcde'
hiraganas = 'あいうえお'
for n, s, h in zip(numbers, alphabets, hiraganas):
    print('{}-{}-{}'.format(n, s, h))
# 0-a-あ
# 1-b-い
# 2-c-う
# 3-d-え
# 4-e-お
```


## while文
次は、while文です。

**Python**

```Python:Python3
i = 0
while i < 5:
    print(i)
    i = i + 1
# 0
# 1
# 2
# 3
# 4

i = 0
while i < 5:
    print(i)
    i += 1
# 0
# 1
# 2
# 3
# 4
```
`i = i + 1`は複合代入演算子`+=`を使って`i += 1`とも書けます。


**R**

```R:R
i <- 0
while (i < 5) {
  print(i)
  i = i + 1
}
# [1] 0
# [1] 1
# [1] 2
# [1] 3
# [1] 4
```

**VBA**

```VBA:VBA
i = 0
Do While i < 5
    Debug.Print i
    i = i + 1
Loop
' 0
' 1
' 2
' 3
' 4
```
VBAでは、`While`の他に`Until`もあります。

```VBA:VBA
i = 0
Do Until i = 5
    Debug.Print i
    i = i + 1
Loop
' 0
' 1
' 2
' 3
' 4
```

同じことをPythonとRで書くならこうなります。
**Python**

```Python:Python3
i = 0
while not i == 5:
    print(i)
    i = i + 1
# 0
# 1
# 2
# 3
# 4
```

**R**

```R:R
i <- 0
while (!(i == 5)) {
  print(i)
  i = i + 1
  
}
# [1] 0
# [1] 1
# [1] 2
# [1] 3
# [1] 4
```


## ループの終了
途中でループを抜ける（繰り返し処理を終了する）方法です。

**Python**

```Python:Python3
for i in range(5):
    if i == 2:
        break
    print(i)
# 0
# 1
```

**R**

```R:R
for (i in 0:4) {
  if (i == 2) {
    break
  }
  print(i)
}
# [1] 0
# [1] 1
```

**VBA**

```VBA:VBA
For i = 0 To 4
    If i = 2 Then
        Exit For
    End If
    Debug.Print i
Next i
' 0
' 1
```
VBAでループを抜けるには、Forループの場合は`Exit For`、Doループの場合は`Exit Do`を使います。


## ループのスキップ
途中のループを飛ばして（スキップして）次のループに移る（次の繰り返し処理に進む）方法です。

**Python**

```Python:Python3
for i in range(5):
    if i == 2:
        continue
    print(i)
# 0
# 1
# 3
# 4
```

**R**

```R:R
for (i in 0:4) {
  if (i == 2) {
    next
  }
  print(i)
}
# [1] 0
# [1] 1
# [1] 3
# [1] 4
```

**VBA**

```VBA:VBA
For i = 0 To 4
    If i = 2 Then
        GoTo continue
    End If
    Debug.Print i
continue:
Next i
' 0
' 1
' 3
' 4
```
VBAにはPythonの`continue`文やRの`next`文のようなループをスキップする文はありません。どうしても使いたいなら`GoTo`を使います。


## その他
Rには`repeat`文というのもありますが、これは`while (TRUE)`（`while`文の条件式に`TRUE`（常に真）を入れたもの）と同じことですので、あまり使い道がなさそうです。

**R**

```R:R
i <- 0
repeat {
  if (i == 2) {
    break
  }
  print(i)
  i = i + 1
}
# [1] 0
# [1] 1

i <- 0
while (TRUE) {
  if (i == 2) {
    break
  }
  print(i)
  i = i + 1
}
# [1] 0
# [1] 1
```

同じことをPythonとVBAで書くならこうなります。

**Python**

```Python:Python3
i = 0
while True:
    if i == 2:
        break
    print(i)
    i += 1
# 0
# 1
```

**VBA**

```VBA:VBA
i = 0
Do While True
    If i = 2 Then
        Exit Do
    End If
    Debug.Print i
    i = i + 1
Loop
' 0
' 1
```


# まとめ
### 一覧
各言語で使用する書き方等を一覧にまとめます。

||Python|R|VBA|
|:--|:--|:--|:--|
|for文|`for i in ...:`<br>　`...`<br>|`for (i in ...) {`<br>　`...`<br>`}`|`For i = ... To ...`<br>　`...`<br>`Next i`|
|while文|`while ...:`<br>　`...`|`while (...) {`<br>　`...`<br>`}`|`Do While ...`<br>　`...`<br>`Loop`|
|until文|`while not ...:`<br>　`...`|`while (!(...)) {`<br>　`...`<br>`}`|`Do Until ...`<br>　`...`<br>`Loop`|
|repeat文|`while True:`<br>　`...`|`repeat {`<br>　`...`<br>`}`|`Do While True`<br>　`...`<br>`Loop`|
|break文|break|break|`Exit For`<br>`Exit Do`|
|continue文|continue|next||


### プログラム全体
参考までに使ったプログラムの全体を示します。

**Python**

```Python:Python3
# for文
for i in range(5):
    print(i)
# 0
# 1
# 2
# 3
# 4
print(range(5))       # range(0, 5)
print(type(range(5))) # <class 'range'>
print(list(range(5))) # [0, 1, 2, 3, 4]

Ns = [2, 3, 5, 7, 11]
for i in range(len(Ns)):
    print(Ns[i])
# 2
# 3
# 5
# 7
# 11

Ns = [2, 3, 5, 7, 11]
for n in Ns:
    print(n)
# 2
# 3
# 5
# 7
# 11

Ns = [2, 3, 5, 7, 11]
for i, n in enumerate(Ns):
    print('Ns[' + str(i) + '] = ' + str(n))
# Ns[0] = 2
# Ns[1] = 3
# Ns[2] = 5
# Ns[3] = 7
# Ns[4] = 11

Ns = [2, 3, 5, 7, 11]
for i, n in enumerate(Ns):
    print('Ns[{}] = {}'.format(i, n))
# Ns[0] = 2
# Ns[1] = 3
# Ns[2] = 5
# Ns[3] = 7
# Ns[4] = 11

numbers = list(range(5))
alphabets = 'abcde'
hiraganas = 'あいうえお'
for n, s, h in zip(numbers, alphabets, hiraganas):
    print('{}-{}-{}'.format(n, s, h))
# 0-a-あ
# 1-b-い
# 2-c-う
# 3-d-え
# 4-e-お

# while文
i = 0
while i < 5:
    print(i)
    i = i + 1
# 0
# 1
# 2
# 3
# 4

i = 0
while i < 5:
    print(i)
    i += 1
# 0
# 1
# 2
# 3
# 4

# untilの代わり
i = 0
while not i == 5:
    print(i)
    i = i + 1
# 0
# 1
# 2
# 3
# 4

# break文
for i in range(5):
    if i == 2:
        break
    print(i)
# 0
# 1

# continue文
for i in range(5):
    if i == 2:
        continue
    print(i)
# 0
# 1
# 3
# 4

# repeat文の代わり
i = 0
while True:
    if i == 2:
        break
    print(i)
    i += 1
# 0
# 1
```

**R**

```R:R
# for文
for (i in 0:4) {
  print(i)
}
# [1] 0
# [1] 1
# [1] 2
# [1] 3
# [1] 4
print(0:4)   # 0 1 2 3 4

Ns <- c(2, 3, 5, 7, 11)
for (i in 1:length(Ns)) {
  print(Ns[i])
}
# [1] 2
# [1] 3
# [1] 5
# [1] 7
# [1] 11

Ns <- c(2, 3, 5, 7, 11)
for (n in Ns) {
  print(n)
}
# [1] 2
# [1] 3
# [1] 5
# [1] 7
# [1] 11

Ns <- c(2, 3, 5, 7, 11)
for (i in 1:length(Ns)) {
  n = Ns[i]
  cat(paste0("Ns[", i, "] = ", n, "\n"))
}
# Ns[1] = 2
# Ns[2] = 3
# Ns[3] = 5
# Ns[4] = 7
# Ns[5] = 11

# while文
i <- 0
while (i < 5) {
  print(i)
  i = i + 1
}
# [1] 0
# [1] 1
# [1] 2
# [1] 3
# [1] 4

# untilの代わり
i <- 0
while (!(i == 5)) {
  print(i)
  i = i + 1
  
}
# [1] 0
# [1] 1
# [1] 2
# [1] 3
# [1] 4

# break文
for (i in 0:4) {
  if (i == 2) {
    break
  }
  print(i)
}
# [1] 0
# [1] 1

# next文
for (i in 0:4) {
  if (i == 2) {
    next
  }
  print(i)
}
# [1] 0
# [1] 1
# [1] 3
# [1] 4

# repeat文
i <- 0
repeat {
  if (i == 2) {
    break
  }
  print(i)
  i = i + 1
}
# [1] 0
# [1] 1

i <- 0
while (TRUE) {
  if (i == 2) {
    break
  }
  print(i)
  i = i + 1
}
# [1] 0
# [1] 1
```

**VBA**

```VBA:VBA
Sub test_repeat()
Dim i As Integer
Dim A As Variant

' for文
For i = 0 To 4
    Debug.Print i
Next i
' 0
' 1
' 2
' 3
' 4

A = Array(2, 3, 5, 7, 11)
For i = LBound(A) To UBound(A)
    Debug.Print A(i)
Next i
' 2
' 3
' 5
' 7
' 11

A = Array(2, 3, 5, 7, 11)
For i = LBound(A) To UBound(A)
    Debug.Print "Ns[" & CStr(i) & "] = " & Str(A(i))
Next i
' Ns [0] = 2
' Ns [1] = 3
' Ns [2] = 5
' Ns [3] = 7
' Ns [4] = 11

' while文
i = 0
Do While i < 5
    Debug.Print i
    i = i + 1
Loop
' 0
' 1
' 2
' 3
' 4

' until文
i = 0
Do Until i = 5
    Debug.Print i
    i = i + 1
Loop
' 0
' 1
' 2
' 3
' 4

' ループからExit
For i = 0 To 4
    If i = 2 Then
        Exit For
    End If
    Debug.Print i
Next i
' 0
' 1
' Doループの場合は、Exit Do

' GoToを使ってcontinue文をVBAで実現
For i = 0 To 4
    If i = 2 Then
        GoTo continue
    End If
    Debug.Print i
continue:
Next i
' 0
' 1
' 3
' 4

' repeat文の代わり
i = 0
Do While True
    If i = 2 Then
        Exit Do
    End If
    Debug.Print i
    i = i + 1
Loop
' 0
' 1

End Sub
```


# 参考
- Python
   - [Python チュートリアル](https://docs.python.org/ja/3/tutorial/index.html)
   - [Chainer チュートリアル　2. Python 入門](https://tutorials.chainer.org/ja/02_Basics_of_Python.html)
- R
   - [RjpWiki](http://www.okadajp.org/RWiki/)
   - [R-Tips](http://cse.naro.affrc.go.jp/takezawa/r-tips/r.html)