zsh を使用して、配列値の文字インデックスに直接新しい値を割り当てます。

zsh を使用して、配列値の文字インデックスに直接新しい値を割り当てます。

文字列配列があり、値から単一文字を変更するには、次のようにします。

$ array=(hello world)
$ array[2]=${array[2]:0:2}X${array[2]:3}
$ echo $array[2]
woXld

このソリューションは機能しますが、実際にはインデックスの値を再割り当てし、変更された文字の前後に元の値の両方を拡張する必要があるため、非常に長い文字列の場合は遅くなります。

配列内の個々の値の文字インデックスを処理することは可能ですが、

$ echo ${array[2][3]}
X

スカラー変数の文字インデックスに新しい値を割り当てます。

$ string='hello world'
$ string[9]=X
$ echo $string
hello woXld

同様の構文は配列では機能しません。

$ array[2][3]=X
zsh: no matches found: array[2][3]=X

最初の方法よりも必要なものをより早く達成する方法はありますか?

ベストアンサー1

これをエレガントに行う方法はないようです。これは、おそらくzsh入れ子になった配列が実際にはサポートされていないため、構文がまだ完全に開発されていないためです。

試すことができる1つの方法は、変更したい文字を切り取るのではなく一時変数を使用することです。

array=(hello world)
tmp=$array[2]
tmp[3]=X
array[2]=$tmp

実際に高速かどうかは、配列の長さ$tmpまたは全体の配列によって異なります。

いくつかのパフォーマンステストを行った結果、興味深い結果が得られました。スカラーのみを処理する場合は、単一文字をインデックス(メソッド)に置き換えます。)

foo[500]=X

左右のパーティションを分割して新しい文字列を作成するよりもはるかに速いようです(方法第二)

foo=${foo:0:499}X${foo:500}

2つをループに入れ、長さが100、1,000、10,000、100,000の文字列に対して100,000回繰り返し、結果は次のとおりです。

./scalar_A100.zsh 100000:         0.16s
./scalar_A1000.zsh 100000:        0.29s
./scalar_A10000.zsh 100000:       1.66s
./scalar_A100000.zsh 100000:     14.63s

 ./scalar_B100.zsh 100000:        0.42s
 ./scalar_B1000.zsh 100000:       1.17s
 ./scalar_B10000.zsh 100000:      5.39s
 ./scalar_B100000.zsh 100000:    46.23s

残念ながら、文字列が配列内にある場合は、文字列の長さ(または配列自体)によって異なります。

配列テストには2つの要素を持つ配列を使用しました。最初の要素は「hello」で、2番目の要素は100から100,000文字の長さの文字列です。

比較的短い文字列を除いて、このメソッドは(一時変数を介して)

foo=$bar[2]
foo[500]=O
bar[2]=$foo

実際、配列要素をスライスに置き換えるよりも遅いです。

bar[2]=${bar[2]:0:499}O${bar[2]:500}

これは、値が実際に一時変数にコピーされ、配列に返されるためです。結果は次のとおりです。

./array_A100.zsh 100000:      0.46s
./array_A1000.zsh 100000:     1.84s
./array_A10000.zsh 100000:   10.50s
./array_A100000.zsh 100000: 101.03s

./array_B100.zsh 100000:      0.60s
./array_B1000.zsh 100000:     1.35s
./array_B10000.zsh 100000:    3.17s
./array_B100000.zsh 100000:  22.13s

また、配列処理は、すべての場合においてスカラー処理よりも遅い。

おすすめ記事