Convert single index into the multiple indices of a tensor product basis
An alternative is to use MixedRadix computations, where the radices are the array dimensions, and taking care of displacements to start at 1 instead of 0. This allows handling one index at a time.
In[1]:= radices = MixedRadix[{2, 3, 2}];
In[2]:= PadLeft[IntegerDigits[#, radices], 3] & /@ Range[0, 11] + 1
Out[2]= {{1, 1, 1}, {1, 1, 2}, {1, 2, 1}, {1, 2, 2}, {1, 3, 1}, {1, 3, 2}, {2, 1, 1}, {2, 1, 2}, {2, 2, 1}, {2, 2, 2}, {2, 3, 1}, {2, 3,2}}
In[3]:= FromDigits[# - 1, radices] + 1 & /@ %
Out[3]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
Your first method seems fine to me. I came up with this without noticing it is similar to yours,
indexToTensorIndices[idx_Integer, lengths_] :=
Join[1 + Quotient[idx, #] & /@ (Reverse@
FoldList[Times, Most@Reverse@lengths]), {Mod[idx, Last@lengths]}]
On extremely large lists of indices it is a bit faster than yours, but yours is pretty fast also.
You could use TuplesFunction
from my answer to Lazy form of Tuples/Outer to loop over list of lists. I won't bother to repeat the definition here as it is a bit long. For the OP example:
tf = TuplesFunction[{Range[2], Range[3], Range[2]}];
tf[Range[12]]
{{1, 1, 1}, {1, 1, 2}, {1, 2, 1}, {1, 2, 2}, {1, 3, 1}, {1, 3, 2}, {2, 1, 1}, {2, 1, 2}, {2, 2, 1}, {2, 2, 2}, {2, 3, 1}, {2, 3, 2}}
Here is a timing comparison of TuplesFunction
with the OP solution:
r1 = indexToTensorIndices[#, {1000, 2000, 3000}]& /@ Range[10^6+1, 10^6+1000]; //RepeatedTiming
tf = TuplesFunction[{Range[1000], Range[2000], Range[3000]}];
r2 = tf[10^6+1 ;; 10^6+1000]; //RepeatedTiming
r1 === r2
{0.013, Null}
{0.0001, Null}
True
Quite a bit faster.