There does not really seem to be a way to do this elegantly. This is probably because zsh
does not actually support nested arrays and the syntax is therefore not fully developed.
One thing you could try is to use a temporary variable instead of slicing around the character you want to change:
array=(hello world)
tmp=$array[2]
tmp[3]=X
array[2]=$tmp
Whether it is actually faster seems to depend on the length of $tmp
or possibly the array as a whole.
I did a bit of performance testing and got some interesting results: If you are handling only scalars, then replacing a single charcter by index (method A)
foo[500]=X
seems to be always much faster than slicing the left and right partitions and building a new string (method B)
foo=${foo:0:499}X${foo:500}
I put both inside a loop with 100,000 iterations for strings of length 100, 1,000, 10,000 and 100,000 with the following results:
./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
Unfortunately, when the string is inside of an array, it depends on the length of the string (or maybe the array itself).
For the array test, I used an array with two elements, the first being "hello" and the second being again a string with lengths between 100 and 100,000 characters.
Except for relativesly short strings, method A (via temporary variable)
foo=$bar[2]
foo[500]=O
bar[2]=$foo
is actually slower than replacing the array element inplace with slices:
bar[2]=${bar[2]:0:499}O${bar[2]:500}
This is due to the values actually being copied into the temporary variable and back into the array. Here are the results for that:
./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
Also note that handling arrays is slower than scalars in every case.