julia を使ってみる 2 (Pythonの利用と文字列）

# juliaからpythonを利用する
[julia を使ってみる 1 (インストールから文字列・整数・浮動小数点・虚数等）](https://qiita.com/percipere/items/a2d5dc78e2e67d89a43c)の続き

##PyCallを利用するために
juliaからpythonを利用できるようにするためのパッケージである[PyCall](https://github.com/JuliaPy/PyCall.jl)を利用してみる

```julia
julia> using Pkg

julia> Pkg.add("PyCall")
  Updating registry at `~/.julia/registries/General`
  Updating git-repo `https://github.com/JuliaRegistries/General.git`
 Resolving package versions...
 Installed Conda ────────── v1.0.1
 Installed JSON ─────────── v0.19.0
 Installed MacroTools ───── v0.4.4
 Installed VersionParsing ─ v1.1.2
 Installed Compat ───────── v1.0.1
 Installed PyCall ───────── v1.17.1
  Updating `~/.julia/environments/v1.0/Project.toml`
  [438e738f] + PyCall v1.17.1
  Updating `~/.julia/environments/v1.0/Manifest.toml`
  [34da2185] + Compat v1.0.1
  [8f4d0f93] + Conda v1.0.1
  [682c06a0] + JSON v0.19.0
  [1914dd2f] + MacroTools v0.4.4
  [438e738f] + PyCall v1.17.1
  [81def892] + VersionParsing v1.1.2
  [2a0f44e3] + Base64 
  [ade2ca70] + Dates 
  [8bb1440f] + DelimitedFiles 
  [8ba89e20] + Distributed 
  [b77e0a4c] + InteractiveUtils 
  [76f85450] + LibGit2 
  [8f399da3] + Libdl 
  [37e2e46d] + LinearAlgebra 
  [56ddb016] + Logging 
  [d6f4376e] + Markdown 
  [a63ad114] + Mmap 
  [44cfe95a] + Pkg 
  [de0858da] + Printf 
  [3fa0cd96] + REPL 
  [9a3f8284] + Random 
  [ea8e919c] + SHA 
  [9e88b42a] + Serialization 
  [1a1011a3] + SharedArrays 
  [6462fe0b] + Sockets 
  [2f01184e] + SparseArrays 
  [10745b16] + Statistics 
  [8dfed614] + Test 
  [cf7118a7] + UUIDs 
  [4ec0a83e] + Unicode 
  Building Conda ─→ `~/.julia/packages/Conda/m7vem/deps/build.log`
  Building PyCall → `~/.julia/packages/PyCall/fiJ3o/deps/build.log`
```

condaを利用してPython環境が構築される

### PyCallを利用してみる

動作しているPythonのバージョンを確認

```julia
julia> py"""
       import sys
       print(sys.version)"""
3.6.5 |Anaconda, Inc.| (default, Apr 26 2018, 08:44:39) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]

```
Pythonとの比較のためにPyCallをインストールしたので、以下利用できる場合はpyを利用してjuliaとPython3の処理を比較する事にする


## juliaの文字列再び

文字列を宣言してその型を調べる

```julia
julia> a = "ABCDEF"
"ABCDEF"

julia> typeof(a)
String
```

特に意味はないが、文字列の型を明記して宣言するなら

```
julia> a = "ABCDEF"::String
"ABCDEF"
```

###部分文字列の利用
文字列から指定の場所の文字を取得できるが、**1-based**なので、インデックスの始まりは1から

```julia
julia> a[0]
ERROR: BoundsError: attempt to access "ABCDEF"
  at index [0]
Stacktrace:
 [1] checkbounds at ./strings/basic.jl:193 [inlined]
 [2] codeunit at ./strings/string.jl:87 [inlined]
 [3] getindex(::String, ::Int64) at ./strings/string.jl:206
 [4] top-level scope at none:0

julia> a[1]
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)

julia> py""" # Pythonの場合
       a = "ABCDEF"
       print(a[0])
       """
A
```

スライスを利用して部分文字列を取得することもできる
range指定の方法は[開始位置:終了位置]


```julia
julia> a[1:2]
"AB"

julia> py""" # Pythonの場合
              a = "ABCDEF"
              print(a[0:2])
              """
AB
```

Pythonとは異なり、開始位置を省略して文字列の先頭を示したり、終了位置を省略するという事はできない

```julia
julia> py"""# Pythonの場合
       a = "ABCDEF"
       print(a[:2])
       print(a[3:])
       print(a[:])
       """
AB
DEF
ABCDEF

julia> a[:2]
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)

julia> a[1:2]
"AB"

julia> a[4:]
ERROR: syntax: missing last argument in "4:" range expression 

julia> a[4:length(a)]
"DEF"

julia> a[:]
"ABCDEF"

```

**開始位置も終了位置も省略するというのはありだったりする　単に `a` となっている**

文字列をスライスを利用して反転する
この場合はrange指定の方法が[開始位置:ステップ:終了位置]となる
**Pythonとは異なるので注意が必要**

```julia
julia> a[length(a):-1:1]
"FEDCBA"

julia> reverse(a)
"FEDCBA"

julia> py""" # Pythonの場合
              a = "ABCDEF"
              print(a[::-1])
              """
FEDCBA
```

(reverse関数を利用しても逆順に並べられる)


#### For ブロック

唐突だが、文字列処理の都合上ここで、forブロックを確認する
**juliaのブロックは必ず`end`で閉じる必要がある**
Pascalっぽいか？

```julia
julia> for i in 1:10
          println(i)
       end
1
2
... # 途中省略
9
10

julia> py""" # Pythonの場合
       for i in range(1, 11):
           print(i)
       """
1
2
... # 途中省略
9
10
```

### 文字列をforループで利用する
文字列を与えてループしてみる

```julia
julia> for c in a
           println(c)
       end
A
B
C
D
E
F

julia> py""" # Pythonの場合
       for c in a:
           print(c)
       """
A
B
C
D
E
F
```

このあたりはPythonと同じように文字列は文字の連続した配列として一文字づつ処理されているようだ

```julia
julia> for c in a
           println(typeof(c))
       end
Char
... # 途中省略
Char
```

この時`c`がCharとして処理されていることがわかる

#### `end`の別の利用方法
ブロックを閉じる`end`だが、キーワードとしてrangeの領域指定に利用するという方法がある
length(a)等とする代わりに `end`が利用できる

```julia
julia> a[3:end]
"CDEF"
```

###行末の処理
行末に改行コード等が入っている場合にこれを取り除くのに`rstrip`関数が利用できる

```julia
julia> b = "ABCDEF\r\n"
"ABCDEF\r\n"

julia> rstrip(b)
"ABCDEF"

julia> length(b)
8

julia> length(rstrip(b))
6

julia> py""" # Pythonの場合
       b = "ABCDEF\r\n"
       print(b.rstrip())
       print(len(b.rstrip()))"""
ABCDEF
6
```

###Delimiterでの文字列の分割
split関数を利用して文字列を分割する

```julia
julia> c = "This is a smaple sentence."
"This is a smaple sentence."

julia> split(c)
5-element Array{SubString{String},1}:
 "This"     
 "is"       
 "a"        
 "smaple"   
 "sentence."

julia> py""" # Pythonの場合
       c = "This is a smaple sentence."
       print(c.split())
       """
['This', 'is', 'a', 'smaple', 'sentence.']
```

###文字列からなる配列の結合
`join(文字列の配列, デリミタ)`関数を利用する 

```julia
julia> d = split(c)
5-element Array{SubString{String},1}:
 "This"     
 "is"       
 "a"        
 "smaple"   
 "sentence."

julia> join(d, " ")
"This is a smaple sentence."

julia> py"""# Pythonの場合
       c = "This is a smaple sentence."
       d = c.split()
       print(d)
       print(" ".join(d))
       """
['This', 'is', 'a', 'smaple', 'sentence.']
This is a smaple sentence.
```


###変数の内挿(Interpolation)
文字列内に変数を埋め込んで文字列を作成できる
**Pythonではf式を利用している**

```julia
julia> println("a: $a, b:$b, c:$c")
a: ABCDEF, b:ABCDEF
, c:This is a smaple sentence.

julia> py""" # Pythonの場合
       a = "ABCDEF"
       b = "ABCDEF\r\n"
       c = "This is a smaple sentence."
       print(f"a: {a}, b:{b}, c:{c}")
       """
a: ABCDEF, b:ABCDEF
, c:This is a smaple sentence.
```

### 文字列内に特定の文字列が有るか調べる
`findfirst`, `findnext`, `findlast`から適宜必要なものを利用すれば良い
存在しない場合には`Nothing`となる
`Nothing`と比較することで`true`または`false`を得る事ができる
**if ではBooleanしか条件判定してくれないので、`true` 又は `false`を得る事が後で必要になる**

```julia
julia> findfirst("AB", a)　# 部分文字列が存在する場合
1:2

julia> typeof(findfirst("AB", a))
UnitRange{Int64}

julia> findfirst("AB", a) !== Nothing
true

julia> findfirst("Z", a)　# 部分文字列が存在しない場合

julia> typeof(findfirst("Z", a))
Nothing

julia> findfirst("Z", a) === Nothing
false

julia> py""" # Pythonの場合
       a = "ABCDEF"
       print("AB" in a)
       print("Z" in a)
       """
True
False
```

###繰り返し文字列の生成
`repeat`関数と`^`関数の利用の2種類がある
なんでこんな事になっているのか
`^`は内部で`repeat`関数を呼んでいるだけだった

```julia
julia> repeat("Wow!", 10)
"Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!"

julia> "Wow!"^10
"Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!"

julia> ^("Wow!", 10)
"Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!"

julia> py""" # Pythonの場合
       print("Wow!"*10)
       """
Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!Wow!
```

その他の関するについてはjuliaのマニュアルの[String](https://docs.julialang.org/en/v1.0.0/base/strings/)の項目に多数列記されている

今回はここまで:smile: