電波ビーチ

☆(ゝω・)v

Goでマルチバイト文字列をインデックス付きでほしい

Goでは文字列型は[]byteとして解釈されるらしいです。

mojiretsu := "💀test♡"
for i:=0; i<len(mojiretsu); i++{
    fmt.Printf("%v ", mojiretsu[i])
}
>>> 240 159 146 128 116 101 115 116 226 153 161

そこで、rune型とかいうのが使われます。forでstring型に対してrangeを使うと、全体に対する1文字ごとのバイト列のインデックス値とrune型が返ります。しれっと書いてますがこの理解であっているか知りません

target := "のじゃロリ狐娘virtualyoutuberおじさん"
for i,v := range target{
   fmt.Printf("index:%d -> %s\n", i, string([]rune{v}))
}

出力がこんな感じになってしまいます

index:0 -> の
index:3 -> じ
index:6 -> ゃ
index:9 -> ロ
index:12 -> リ
index:15 -> 狐
index:18 -> 娘
index:21 -> v
index:22 -> i
index:23 -> r
index:24 -> t
index:25 -> u
index:26 -> a
index:27 -> l
index:28 -> y
index:29 -> o
index:30 -> u
index:31 -> t
index:32 -> u
index:33 -> b
index:34 -> e
index:35 -> r
index:36 -> お
index:39 -> じ
index:42 -> さ
index:45 -> ん

インデックスが文字ごとではなく、全体をバイト列とみたときに該当する文字の箇所の最初のインデックスになっています。

外部にインデックス用の変数を用意しとくのも手ですがそれだけのために冗長です。いっそforのスコープ内で作れればいいのですがrangeを使っている関係上(たぶん)これ以上簡易文で変数は作れないです。わからんけど

cur := 0
for _,v := range target{
     fmt.Printf("index:%d -> %s\n", cur, string([]rune{v}))
     cur+=1
}

rangeに渡すときに文字列を[]runeとしてやればいいです。

for i, v:=range []rune(target){
     fmt.Printf("index: %d -> %s\n", i, string(v))
}