# Modify the start and end index of a function involving RuleDelayed

I have a list $$\{a,b,c,d,e,f\}$$ and an array of variables $$\{y[1],y[2],y[3],y[4],y[5],y[6]\}$$. I want to use the RuleDelayed function represented by the symbol :> to replace the variables with the elements on the list $$\{a,b,c,d,e,f\}$$. The code is written as,

list={a,b,c,d,e,f};
array=Array[y, 6];
array/.y[i_] :> list[[i]]


However, I want the RuleDelayed function :> to replace $$\{y[2],y[3],y[4],y[5]\}$$ with $$b,c,d,e$$ excluding the first and last terms so that I have {y[2]:>b,y[3]:>c,y[4]:>d,y[5]:>e}, i.e., the function y[i_] starts from i=2 and ends at i=5. The question is, how should I modify the function y[i_] :> list[[i]] so that the index starts at i=2 and ends at i=5?

Please do not respond by saying that I should just generate an array from y[2] to y[5]. I asked this question while using RuleDelayed to understand how to modify the function y[i_].

• list = {b, c, d, e}; array /. y[i_ /; 1 < i < 6] :> list[[i - 1]] Commented Dec 25, 2022 at 17:52
• "...modify the function y[i_]", does this mean you actually want to set DownValues for y? I.e. you want to end up with definitions like y[2]=a and so forth? Commented Dec 25, 2022 at 19:10
• Do you need it to work for arbitrary sized lists? Like for any given length for array and list do you want the rule to always be "centered"? Commented Dec 25, 2022 at 19:18
• Just for clarity’s sake, with OP’s second list example, list[[2]] would give c, rather than b, as it seems to be implied by OP. Unless, of course, the second list example is being compared with the first, in some way? This needs more information, to be sure. Commented Dec 26, 2022 at 4:08
• @lericr DownValues? I guess not. Yes, I want it for arbitrary sized list and basically, if you give me a list of length n. I want to replace {y[2], ..., y[n-1]} with it, i.e., the array of y starts at i=2 and ends at i=n-1. However, I want to do this using RuleDelayed. Commented Dec 26, 2022 at 8:07

array /. y[i_] :> If[Length[array] > i > 1, list[[i]], Nothing]
(* {b, c, d, e} *)


You may create a table of rules that depend on the length of list. If the length is 6 we would have: y[1]:>list[[1],.. however if the list starts with b, we would have: y[2]->b,..:

list = {a . b, c, d, e, f};
Array[y[# - Length[list] + 6] &, Length[list]] -> list]
array /. rules
(* {a, b, c, d, e, f} *)


However with a shorter list:

list = {b, c, d, e, f};
Array[y[# - Length[list] + 6] &, Length[list]] -> list]
array /. rules
(* y[1], b, c, d, e, f} *)

list = {c, d, e, f};
Array[y[# - Length[list] + 6] &, Length[list]] -> list]
array /. rules
(* {y[1], y[2], c, d, e, f} *)


I'm interpreting the question as asking how to generate the replacement rule and not actually doing the replacement. I'm also interpreting the comment about not generating the array to mean that we don't want any sort of "threaded" structure, but an indexed-based rule. And finally, the OP indicated in a comment that it should work for arbitrarily sized lists. Here's a function that might work:

CenteredRule[fn_Symbol, fnLength_Integer?Positive, vals_List] :=
With[
{offset = Floor[(fnLength - Length@vals)/2]},
fn[i_Integer] :> vals[[i - offset]] /; offset < i <= offset + Length@vals]


Examples:

CenteredRule[y, 6, {b, c, d, e}]


y[i$_] :> {b, c, d, e}[[i$ - 1]] /; 1 < i$<= 1 + Length[{b, c, d, e}] CenteredRule[y, 4, {a, b, c, d, e, f}]  y[i$_] :> {a, b, c, d, e, f}[[i$- -1]] /; -1 < i$ <= -1 + Length[{a, b, c, d, e, f}]

Applications:

Array[z, 7] /. CenteredRule[z, 7, {b, c, d, e}]


{z[1], b, c, d, e, z[6], z[7]}

Array[w, 4] /. CenteredRule[w, 4, {a, b, c, d, e, f, g}]


{c, d, e, f}

Array[q, 9, {-2, 6}] /. CenteredRule[q, 3, {a, b, c, d, e, f, g}]


{q[-2], a, b, c, d, e, f, g, q[6]}

Array[q, 9, {1, 5}] /. CenteredRule[q, 5, {a, b, c, d, e, f, g}]


{b, q[3/2], c, q[5/2], d, q[7/2], e, q[9/2], f}

Array[q, 9, {1, 5}] /. CenteredRule[q, 5, {a, b, c}]


{q[1], q[3/2], a, q[5/2], b, q[7/2], c, q[9/2], q[5]}