2022/12/18 JuliaTokai #13
antimon2(後藤 俊介)
Note:
Julia の基本Tips?
Note:
今日は(も?)大っぴらに Julia の話ができるっ
Note:
普段は Python で仕事してますっ
https://ngk2022s.connpass.com/event/265837/
Note:
MGK2023S のスタッフやってますっ
Note:
Julia の紹介っ
Note:
こんなロゴですっ
Note:
ググるときはなるべく julialang で!
- Rのように中身がぐちゃぐちゃでなく、
- Rubyのように遅くなく、
- Lispのように原始的またはエレファントでなく、
- Prologのように変態的なところはなく、
- Javaのように硬すぎることはなく、
- Haskellのように抽象的すぎない
ほどよい言語である
引用元:http://www.slideshare.net/Nikoriks/julia-28059489/8
- C のように高速だけど、
Ruby のようなダイナミズムを併せ持っている- Lisp のようにプログラムと同等に扱えるマクロがありながら、
MATLAB のような直感的な数式表現もできる- Python のように総合的なプログラミングができて、
R のように統計処理も得意で、
Perl のように文字列処理もできて、
MATLAB のように線形代数もできて、
shell のように複数のプログラムを組み合わせることもできる- 超初心者にも習得は容易でありながら、
超上級者の満足にも応えられる- インタラクティブにも動作して、コンパイルもできる
(Why We Created Julia から抜粋・私訳)
Note:
いろんな言語の「いいとこどり」言語!ってことでっ
Note:
機械学習とかにも持って来いっ!
Note:
っ
Note:
以降、ほぼ過去スライドからのコピペ。すっ飛ばして先へ進んで戴いてもOKっ
julia> 1 + 2 - 3 * 4 # 四則演算(除算以外)
-9
julia> 7 / 5 # `整数 / 整数` の結果は浮動小数
1.4
julia> 7 ÷ 5 # `整数 ÷ 整数` の結果は整数
1
julia> 2 ^ 10 # 冪乗は `^`
1024
julia> 123 & 234 | 345 # 論理積 / 論理和
376
julia> 123 ⊻ 234 # 排他的論理和(==`xor(123, 234)`)
145
Note:
整数同士の除算は実数になりますっ
整数除算演算子 ÷
が別に存在します(Python の //
相当)っ
また冪乗も(**
ではなく)^
ですっ
⊻
は \xor
+Tab または \veebar
+Tab で変換できますっ
ちなみに先ほどの ÷
も \div
+Tabで(基本的に \({\rm \TeX}\) の書式)っ
julia> a = [1, 2, 3, 4, 5]
5-element Vector{Int64}:
1
2
3
4
5
julia> a[1] # Julia は 1-origin
1
julia> println(a[2:3]) # 範囲指定は両端含む
[2, 3]
Note:
1-origin であることに注意すればあとは普通の配列っ
あと a:b
は範囲(Range
)の記法。両端を含む(Ruby の a..b
と同じ)っ
julia> a = [n^2 for n=1:5]
5-element Vector{Int64}:
1
4
9
16
25
julia> A = [x+10y for y=1:3, x=1:3]
3×3 Matrix{Int64}:
11 12 13
21 22 23
31 32 33
Note:
内包表記の記法は Python に類似っ
かつ、for
にカンマ区切りで複数のイテレータを渡すことで2次元以上の配列も作成可能っ
julia> [(a,b,c) for c=1:15,b=1:15,a=1:15 if a^2+a*b+b^2==c^2]
6-element Vector{Tuple{Int64, Int64, Int64}}:
(3, 5, 7)
(5, 3, 7)
(6, 10, 14)
(7, 8, 13)
(8, 7, 13)
(10, 6, 14)
Note:
Python と同様に if
で条件を指定することも可能っ
あと Python と同様、[○ for ○=○]
を (○ for ○=○)
と書くと配列ではなくて Generator
が返りますっ
julia> [1;2;;3;4;;;5;6;;7;8] # 2×2×2 の3次元配列
2×2×2 Array{Int64, 3}:
[:, :, 1] =
1 3
2 4
[:, :, 2] =
5 7
6 8
julia> [1 2;3 4;;;5 6;7 8] # 従来記法との併用も可能(次元の順番に注意)
2×2×2 Array{Int64, 3}:
[:, :, 1] =
1 2
3 4
[:, :, 2] =
5 6
7 8
julia> [1;;;;] # 1×1×1×1 の4次元配列
1×1×1×1 Array{Int64, 4}:
[:, :, 1, 1] =
1
Note:
;
の数で次元方向の区切ができるっ
これだけでも v1.7 を使うべきと言える仕様拡張っ!
julia> x = [1., 2., 3.]; y = [3., 1., 2.];
julia> x + y # `x .+ y` と書いても同じ(elementwise operation)
[4., 3., 5.]
julia> x .* y # これは `x * y` と書くとNG
[3., 2., 6.]
julia> using LinearAlgebra
julia> x ⋅ y # 内積(dot積、`dot(x, y)` と書いても同じ)
11.0
julia> x × y # 外積(cross積、`cross(x, y)` と書いても同じ)
[1., 7., -5.]
Note:
Julia では実は1次元配列がベクトルの扱いっ
⋅
は \cdot
+Tab、×
は \times
+Tab(これらを利用するには using LinearAlgebra
必要)っ
あとこれらや先ほどの ÷
や ⊻
などのように、ASCIIの範囲を超えたUnicode文字の演算子(そのほとんどが \(\TeX\) 由来)が Julia にはたくさんあります(他には例えば比較演算子の ≤
≥
や、集合の要素 ∈
や包含関係 ⊆
などなど)
julia> A = [1 2; 3 4] # この記法は MATLAB/Octave 由来
2×2 Matrix{Int64}:
1 2
3 4
julia> A' # `○'` は転置行列(正確には随伴行列)の記法(これも MATLAB/Octave 由来)
2×2 adjoint(::Matrix{Int64}) with eltype Int64:
1 3
2 4
julia> A'ᵀ # ← ≥ v"1.6", v"1.5" までは `transpose(A)` # 正確には転置行列はこっち
2×2 transpose(::Matrix{Int64}) with eltype Int64:
1 3
2 4
Note:
Julia では2次元配列が行列の扱いっ
v1.6 から転置を表す表記として ○'ᵀ
と書けるようになりましたっ
'\^T
+ TAB で入力できますっ
julia> A = [1 2; 3 4]; B = [3 0; 0 6];
julia> A + B # A .+ B でも同様
2×2 Matrix{Int64}:
4 2
3 10
julia> A * B # matrix multiply
2×2 Matrix{Int64}:
3 12
9 24
julia> A .* B # elementwise multiply
2×2 Matrix{Int64}:
3 0
0 24
Note:
行列は *
で通常の行列積になりますっこれ便利っ
julia> sin(0.1)
0.09983341664682815
julia> sin.([0.1, 0.2, 0.3, 0.4])
4-element Vector{Float64}:
0.0998334
0.198669
0.29552
0.389418
julia> [0.1, 0.2, 0.3, 0.4] .^ 2
# => [0.01, 0.04, 0.09, 0.16]
Note:
関数名と (
の間に .
を置くと、普通の関数を配列に拡張してくれる(ブロードキャスト)っ
.^
のように演算子の前に .
を書いても同様(先ほど出た .+
.*
もブロードキャスト)っ
julia> f(x) = x^2 + 2x - 1
f (generic function with 1 method)
julia> f(1)
2
julia> f.(1:5)
# => [2, 7, 14, 23, 34]
Note:
数学のように直感的な記述で関数を定義可能っ
2x
は 2*x
の省略形、曖昧さがなければリテラルと他の識別子が続く場合などに勝手に乗算と解釈してくれるっ
またユーザ定義関数も .
をつけて自動的にブロードキャスト対応っ
julia> 1//2 == 0.5
true
julia> 1//2 - 1//3
1//6
julia> 1im ^ 2 == -1
true
julia> (1.0 + 0.5im) * (2.0 - 3.0im)
3.5 - 2.0im
Note:
有理数・複素数を標準サポート。
//
は有理数除算(結果は有理数)
im
は虚数単位。
どちらも四則演算も普通に書けますっ
Note:
本題!
findXXX()
系関数?findXXX()
系の関数って、こういうとき使えるの?⇒
Note:
…
for
文で回せばOKNote:
…
# 同じ要素がN個続く箇所を見つけてそのインデックスの範囲を返す
function findNrepeats(a::AbstractVector, N)
_lastindex = lastindex(a)
for i in eachindex(a) # keys(a) でもOK
r = i:i+N-1
last(r) > _lastindex && break
allequal(a[r]) && return r
end
nothing
end
Note:
…
julia> a = [0, 7, 7, 5, 0, 0, 0, 1, 1, 2]; # a[5:7] == [0, 0, 0]
julia> findNrepeats(a, 3)
5:7
julia> findNrepeats([3, 1, 4, 1, 5, 9, 2, 6, 5, 3], 2) === nothing
true
Note:
…
findXXX()
を利用する形に落とし込むNote:
…
# 同じ要素がN個続く箇所を見つけてそのインデックスの範囲を返す ver.2
function findNrepeats_v2(a::AbstractVector, N)
rs = [i:i+N-1 for i in eachindex(a) if i+N-1 ≤ lastindex(a)]
index = findfirst(rs) do r
allequal(a[r])
end
isnothing(index) ? nothing : rs[index]
end
Note:
…
julia> a = [0, 7, 7, 5, 0, 0, 0, 1, 1, 2]; # a[5:7] == [0, 0, 0]
julia> findNrepeats_v2(a, 3)
5:7
julia> findNrepeats_v2([3, 1, 4, 1, 5, 9, 2, 6, 5, 3], 2) === nothing
true
Note:
…
Note:
…
julia> using BenchmarkTools, Random
julia> N=3;
julia> Random.seed!(1234);
@benchmark findNrepeats(a, $N) setup=(a=rand(0:9, 100))
# 出力例は画像参照
julia> Random.seed!(1234);
@benchmark findNrepeats_v2(a, $N) setup=(a=rand(0:9, 100))
# 出力例は画像参照
Note:
…
Note:
…
findXXX()
は「条件に合致するもののインデックス(の範囲)を返す関数(存在しなければ nothing
)」という共通仕様
findmax()
/ findmin()
for i in eachindex(a)
または for i in keys(a)
for i in 1:length(a)
は危険!Note:
※ Julia の findXXX()
系の関数は「条件に合致するもののインデックス(の範囲)を返す関数(存在しなければ nothing
)」という共通仕様がある(例外:findmax()
/findmin()
)ので、findNrepeats()
もそれに合わせた仕様にしてあります。
※ Julia のインデックスは(標準の1次元配列なら)1-originだけど、全てのコレクションのインデックスがそうとは限らない(設定次第)ので for i in 1:length(a)
のように書くのは危険!
findXXX()
系の関数は正直使いづらいし、必ずしも高パフォーマンスとは限らない。for
ループ速い!allequal()
て関数知ってた?Note:
※ あと「コレクションの要素が全て同じかどうか」を判定するズバリ allequal()
て関数が標準であります。便利♪知ってました?
なお「コレクションの要素が全て異なるかどうか」を判定する allunique()
てのもあります。
findfirst()
でOK!Note:
…
# 前準備:「同じ文字のN回繰り返し」という正規表現を生成しキャッシュする仕組み
@generated function getNrepeatsRegex(::Val{N}) where {N}
Regex("(.)" * "\\1" ^ (N-1)) # N=3 なら `r"(.)\1\1"` となる
end
# 同じ文字がN個続く箇所を見つけてそのインデックスの範囲を返す
function findNrepeats(s::AbstractString, N)
rex = getNrepeatsRegex(Val(N))
findfirst(rex, s)
end
Note:
…
julia> s = "ABC123あああ😁漢字"; # s[7:13] == "あああ"
julia> findNrepeats(s, 3)
7:13
Note:
…
findXXX()
でOK(キャッシュしないバージョン)Note:
…
# 同じ要素がN個続く箇所を見つけてそのインデックスの範囲を返す ver.2
function findNrepeats_v2(s::AbstractString, N)
rex = Regex("(.)" * "\\1" ^ (N-1)) # N=3 なら `r"(.)\1\1"`
findfirst(rex, s)
end
Note:
…
julia> s = "ABC123あああ😁漢字"; # s[7:13] == "あああ"
julia> findNrepeats_v2(s, 3)
7:13
Note:
…
Note:
…
julia> using BenchmarkTools, Random
julia> N=3;
julia> Random.seed!(1234);
@benchmark findNrepeats(s, $N) setup=(
s=randstring("123ABCあいう😁漢字", 100))
# 出力例は画像参照
julia> Random.seed!(1234);
@benchmark findNrepeats_v2(s, $N) setup=(
s=randstring("123ABCあいう😁漢字", 100))
# 出力例は画像参照
Note:
…
Note:
…
findXXX()
は文字列検索の場合パターン(正規表現、文字の範囲等)も利用OK!@generated
(生成関数)こういうとき便利♪Note:
※ findXXX
は文字列検索の場合第1引数は関数だけではなくパターン(正規表現、文字の範囲等)もOK!
※ ただし毎回正規表現を生成するのは意外とコスト高い(=遅い)ので何らかの方法でキャッシュする必要あり(正規表現リテラルが使用できるなら使用するなど)
※ てかこのサンプルを作ることで @generated
(生成関数)の使い途を1つ見つけてしまった♪これ基本!
findXXX()
(第1引数に関数を受け取る使い方)Note:
→ 配列や文字列だけじゃなくて、辞書(Dict
)や名前付きタプル(NamedTuple
)にも同じI/Fで利用できるから(それらの場合キー(の列)が返る)。
julia> D = Dict(["Carol", "Alice", "Ellen", "Bob", "Dave"].=>1:5);
julia> findall(isodd, D) # 値が奇数であるようなエントリーのキーを全て列挙
3-element Vector{String}:
"Carol"
"Dave"
"Ellen"
julia> [D[key] for key in findall(isodd, D)]
3-element Vector{Int64}:
1
5
3
julia> # ※ ↑は結果的に `filter(isodd, collect(values(D)))` と同じ
Note:
…
findXXX()
系関数findXXX()
系関数の理念や使い途は分かった。分かったけれどやっぱ使いにくい!
nothing
)」っていう関数はないの?⇒
Note:
…
Iterators.dropwhile()
と Base.first()
を組み合わせればOKNote:
…
# 第1引数で条件判定して、第2引数のコレクションで最初に合致する要素を返す
# (なければ `nothing`)
function meetfirst_v1(pred::Function, itr)
# NG: `return first(Iterators.dropwhile(!pred, itr))`
itr2 = Iterators.dropwhile(!pred, itr)
try
first(itr2)
catch e
if isa(e, BoundsError) || isa(e, ArgumentError)
return nothing
end
rethrow(e)
end
end
Note:
…
julia> a = [314, 159, 265, 358, 979, 323, 846, 264];
julia> meetfirst_v1(n -> n % 11 == 0, a)
979
julia> meetfirst_v1(n -> n % 7 == 0, a) === nothing
true
Note:
…
julia> # コラッツ数列を列挙するイテレータ(`Channel`)を返す関数
function collatz(n::Int)
Channel{Int}() do chnl
put!(chnl, n)
while n > 1
n = iseven(n) ? n ÷ 2 : 3n + 1
put!(chnl, n)
end
end
end
collatz (generic function with 1 method)
julia> meetfirst_v1(≥(200), collatz(27))
214
julia> meetfirst_v1(≥(50), collatz(3)) === nothing
true
Note:
…
Note:
…
# 第1引数で条件判定して、第2引数のコレクションで最初に合致する要素を返す
# (なければ `nothing`) ver.2
function meetfirst(pred::Function, itr)
itr2 = Iterators.dropwhile(!pred, itr)
next = iterate(itr2)
isnothing(next) ? nothing : first(next) # `first(next)` はタプルの第1要素を取得している
end
Note:
…
julia> a = [314, 159, 265, 358, 979, 323, 846, 264];
julia> meetfirst(n -> n % 11 == 0, a)
979
julia> meetfirst(n -> n % 7 == 0, a) === nothing
true
Note:
…
julia> # コラッツ数列を列挙するイテレータ(`Channel`)を返す関数
function collatz end; # 長いので略
julia> meetfirst(≥(200), collatz(27))
214
julia> meetfirst(≥(50), collatz(3)) === nothing
true
Note:
…
Note:
…
julia> using BenchmarkTools, Random
julia> Random.seed!(1234);
@benchmark meetfirst_v1(≥(200), c) setup=(c=collatz(rand(3:100)))
# 出力例は画像参照
julia> Random.seed!(1234);
@benchmark meetfirst(≥(200), c) setup=(c=collatz(rand(3:100)))
# 出力例は画像参照
Note:
…
Note:
…
first(Iterators.dropwhile(!pred, itr))
!《関数》
は x -> !(《関数》(x))
相当first(《空のイテレータ》)
は例外が発生してしまうので適切に対処Note:
※ 基本的な発想は first(Iterators.dropwhile(!pred, itr))
※ !pred
というのは、pred()
関数の結果(Bool
値 という前提)を否定、つまり x->!(pred(x))
相当
※ first(《空のイテレータ》)
は例外が発生してしまうので適切な対処が必要
iterate(itr)
:
(《要素》, 《状態オブジェクト》)
nothing
Note:
※ Julia のイテレーションの仕組み(iterate()
関数の使い方・戻り値)を知っていれば、first()
関数相当のことを簡単に実現できてしかも例外処理不要!(Julia の例外処理は意外と重い!)
※ (簡単におさらい) iterate(itr)
は、最初の要素があるときは (《要素》, 《状態オブジェクト》)
、なければ nothing
⇒
Note:
\
を入れることで折り返しできる(ようになった)よ!(≥v1.7)Note:
…
julia> jgm0 = "寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末食う寝る処に住む処やぶらこうじのぶらこうじパイポ・パイポ・パイポのシューリンガン・シューリンガンのグーリンダイ・グーリンダイのポンポコピーのポンポコナの長久命の長助";
julia> jgm1 = "寿限無寿限無五劫の擦り切れ\
海砂利水魚の水行末雲来末風来末\
食う寝る処に住む処やぶらこうじのぶらこうじ\
パイポ・パイポ・パイポのシューリンガン・\
シューリンガンのグーリンダイ・グーリンダイのポンポコピーのポンポコナの\
長久命の長助";
Note:
…
julia> jgm2 = """
寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末\
食う寝る処に住む処やぶらこうじのぶらこうじ\
パイポ・パイポ・パイポのシューリンガン・シューリンガンのグーリンダイ・\
グーリンダイのポンポコピーのポンポコナの\
長久命の長助""";
# ↑ `"""~"""` ならインデントも無視されるのでさらに見やすく!
Note:
…
julia> jgm0 == jgm1 == jgm2 # もちろん文字列として同一視できる
true
julia> jgm0 === jgm1 === jgm2 # リテラルとしても同一になる(今回の場合)!
true
Note:
※リテラルとして同一になる(今回の場合)ので ===
で比較しても true
になる!
Note:
Julia v1.6.x 以前を捨てて良いコードならば。
julia> jgm0 = "寿限無寿限無五劫の擦り切れ海砂利水魚の水行末雲来末風来末食う寝る処に住む処やぶらこうじのぶらこうじパイポ・パイポ・パイポのシューリンガン・シューリンガンのグーリンダイ・グーリンダイのポンポコピーのポンポコナの長久命の長助";
julia> jgm_oldstyle =
"寿限無寿限無五劫の擦り切れ" *
"海砂利水魚の水行末雲来末風来末" *
"食う寝る処に住む処やぶらこうじのぶらこうじ" *
"パイポ・パイポ・パイポのシューリンガン・" *
"シューリンガンのグーリンダイ・グーリンダイのポンポコピーのポンポコナの" *
"長久命の長助";
julia jgm0 == jgm_oldstyle
true
Note:
※ なお最適化の関係でこれくらいの長さの文字列ならたぶん jgm0 === jgm_oldstyle
になります。。。
OrderedDict
とか SortedSet
とかDict
や Set
って順不同ですよね…OrderdDict
とか SortedSet
欲しい…⇒
Note:
Dict
や Set
って追加順やキーの序列と列挙順が順不同ですよね…OrderdDict
とか SortedSet
欲しい…ん…DataStructures
にあるからそれ使うのが素直な解決法Note:
…
julia> # 標準の Dict: 順不同
dic = Dict(["Carol", "Alice", "Ellen", "Bob", "Dave"].=>1:5)
Dict{String, Int64} with 5 entries:
"Carol" => 1
"Alice" => 2
"Dave" => 5
"Ellen" => 3
"Bob" => 4
Note:
…
(@v1.x) pkg> add DataStructures
# 出力例略
julia> using DataStructures
julia> # OrderedDict: 追加順
odic = OrderedDict(["Carol", "Alice", "Ellen", "Bob", "Dave"].=>1:5)
OrderedDict{String, Int64} with 5 entries:
"Carol" => 1
"Alice" => 2
"Ellen" => 3
"Bob" => 4
"Dave" => 5
Note:
…
julia> # 標準の Set: 順不同
set = Set(["Carol", "Alice", "Ellen", "Bob", "Dave"])
Set{String} with 5 elements:
"Carol"
"Alice"
"Dave"
"Ellen"
"Bob"
Note:
…
(@v1.x) pkg> add DataStructures
# 出力例略
julia> using DataStructures
julia> # SortedSet: 値の昇順
sset = SortedSet(["Carol", "Alice", "Ellen", "Bob", "Dave"])
SortedSet{String, Base.Order.ForwardOrdering} with 5 elements:
"Alice"
"Bob"
"Carol"
"Dave"
"Ellen"
Note:
…
Vector
でキーの列を別管理するNote:
列挙時にだけ追加順/ソート順が欲しい場合
julia> dkeys = ["Carol", "Alice", "Ellen", "Bob", "Dave"];
julia> dic = Dict(dkeys.=>1:5)
Dict{String, Int64} with 5 entries:
"Carol" => 1
"Alice" => 2
"Dave" => 5
"Ellen" => 3
"Bob" => 4
Note:
…
julia> # 追加順に列挙
for key in dkeys
println("$(key) => $(dic[key])")
end
Carol => 1
Alice => 2
Ellen => 3
Bob => 4
Dave => 5
Note:
…
julia> # キーの昇順に列挙
for key in sort(dkeys)
println("$(key) => $(dic[key])")
end
Alice => 2
Bob => 4
Carol => 1
Dave => 5
Ellen => 3
Note:
…
DataStructures.jl
便利♪
OrderedDict
/SortedSet
の他に SortedDict
/OrderedSet
ももちろんあるNote:
…
Vector
で別管理するのもお手軽で十分
Note:
※ その分メモリを消費するが、列挙時にだけ追加順/ソート順が欲しいならそれで十分
※ ↑の「解決2」でもそんなに困らない(長さが膨大でなければ)
fn = x -> x*x
⇒ fn(x, y)
はメソッドエラー(まぁ当然)fn(x) = x*x
→ fn(x, y) = ~
と多重定義できる⇒
Note:
fn = x -> x*x
みたいにして関数を定義すると、fn(x, y)
のような呼び出しは失敗しますよね。多重定義されていないから。fn(x) = x*x
という定義にすれば良い、そうすれば後で fn(x, y) = ~
と多重定義できる、それは分かります。Note:
…
julia> fn = x -> x * x
#45 (generic function with 1 method)
julia> # 関数 `fn`(正確には変数 `fn` に格納されている無名関数)の多重定義
(::typeof(fn))(x, y) = x * y
julia> methods(fn)
# 2 methods for anonymous function "#45":
[1] (::var"#45#46")(x) in Main at REPL[121]:1
[2] (::var"#45#46")(x, y) in Main at REPL[122]:2
julia> @show fn(5) fn(5, 8)
fn(5) = 25
fn(5, 8) = 40
40
Note:
…
Note:
※ 重要:できるけれどほぼ使い途はありません!
s = "123ABCあいう😁漢字"
に対して「s
の10文字目」と指定して「'😁'
」を取得したい…。⇒
Note:
s = "123ABCあいう😁漢字"
に対して「s
の10文字目」と指定して「'😁'
」を取得したい…。nextind()
という関数が用意されています!Note:
…
help?> nextind
search: nextind IndexCartesian MissingException current_exceptions InterruptException InvalidStateException
nextind(str::AbstractString, i::Integer, n::Integer=1) -> Int
# :《中略》
• Case n > 1
Behaves like applying n times nextind for n==1. The only difference is that if n is so large that applying
nextind would reach ncodeunits(str)+1 then each remaining iteration increases the returned value by 1.
This means that in this case nextind can return a value greater than ncodeunits(str)+1.
# :《以下略》
Note:
…
julia> s = "123ABCあいう😁漢字";
julia> nextind(s, 0, 10) # `0` より後で `10` 番目の文字のインデックス
16
julia> s[nextind(s, 0, 10)] # `s` の10文字目
'😁': Unicode U+1F601 (category So: Symbol, other)
Note:
…
xxxxind()
系の関数julia> # `thisind()`: 指定したあたりに存在する文字の正しいインデックス番号を返す
julia> s = "123ABCあいう😁漢字";
julia> thisind(s, 9)
7
julia> s[thisind(s, 9)]
'あ': Unicode U+3042 (category Lo: Letter, other)
julia> # `prevind()`:「後ろから何文字目」という指定が可能
julia> s[prevind(s, end+1, 3)] # 後ろから3文字目の文字
'😁': Unicode U+1F601 (category So: Symbol, other)
Note:
…
eachindex()
関数julia> s = "123ABCあいう😁漢字";
julia> # 文字列の全てのインデックスを列挙するなら↓
julia> eachindex(s)
Base.EachStringIndex{String}("123ABCあいう😁漢字")
julia> collect(eachindex(s))
12-element Vector{Int64}:
1
2
3
4
5
6
7
10
13
16
20
23
Note:
…
split()
の場合julia> s = "123ABCあいう😁漢字";
julia> split(s, "")[10]
"😁"
Note:
※似たようなことはできるが以下が異なる:
Char
)ではなく文字列(SubString{String}
)になるNote:
っ
ご清聴ありがとうございます。
Note:
ご清聴ありがとうございますっ!