Function Repository Resource:

SpanRange

Source Notebook

Construct an explicit position range from a span specification

Contributed by: Nikolay Murzin

ResourceFunction["SpanRange"][span,length]

returns arguments for Range representing span over an expression of a given non-negative integer or infinite length.

ResourceFunction["SpanRange"][span, expr]

derives the length from a given expression expr.

ResourceFunction["SpanRange"][span]

assume length is equal to Infinity.

Details

span can be a Span taking a general form of left;;right;;step.
Any argument of span (left, right or step) can be All, in which case it is interpreted as returning the largest possible number of elements consistent with any possible value of that argument.
The left and right parameters of a span are considered ordinals indexing parts of an expression with a given length, with 0 pointing to the Head of an expression, negative integers indexing from the end with Infinity corresponding to the last part.
length can be Infinity and infinite ranges like {1,, 1} (invalid for Range) can be produced.
Span specifications of the form left;;UpTo[n] and UpTo[n];;right will result in a range with a maximum of n elements (n is treated as a cardinal).
UpTo[n];;UpTo[m] will result in a range with a maximum of Min[n,m] elements.
UpTo[Infinity] in the left or right place is the same as All.
UpTo[-n] is also supported for left or right places of a Span, it would complaint, but the result would be equivalent to its complement UpTo[Max[len-n,0]].
UpTo[-n] is also supported for left or right places of a Span. The result is equivalent to its complement UpTo[Max[len-n,0]]. Messages produced by UpTo can be quieted or ignored.
If span is a valid non-zero expression from above then it's equivalent to 1 ;; span, but 0 ;; 0 when it is zero.
span can be equal to UpTo[n] which is equivalent to ;;UpTo[n], and -UpTo[n] is equivalent to UpTo[n];;.
If span is a list with single {n}, two {n,m} or three {n,m,k} elements then it's equivalent to n;;n, n;;m and n;;m;;k respectively.
span can also be a Composition (@*) or RightComposition (/*) of the above span specifications.
Some spans including 0 are invalid when used as a Part specification but are still supported in ResourceFunction["SpanRange"].

Examples

Basic Examples (2) 

Get a range from a span specification:

In[1]:=
ResourceFunction["SpanRange"][3 ;; 7, 10]
Out[1]=
In[2]:=
Range @@ %
Out[2]=

Get another range from span specification:

In[3]:=
ResourceFunction["SpanRange"][2 ;; 9 ;; 2, 10]
Out[3]=
In[4]:=
Range @@ %
Out[4]=

Scope (14) 

Negative integers encode position from the right side of the sequence:

In[5]:=
ResourceFunction["SpanRange"][3 ;; -3, 10]
Out[5]=
In[6]:=
ResourceFunction["SpanRange"][-7 ;; 7, 10]
Out[6]=
In[7]:=
ResourceFunction["SpanRange"][-6 ;; -2, 10]
Out[7]=

Negative step:

In[8]:=
ResourceFunction["SpanRange"][7 ;; 3 ;; -1, 10]
Out[8]=
In[9]:=
ResourceFunction["SpanRange"][9 ;; 2 ;; -2, 10]
Out[9]=

All in the left or right span position maximizes number of elements spanned by choosing one of two boundary indices:

In[10]:=
ResourceFunction["SpanRange"][All ;; 3, 10]
Out[10]=
In[11]:=
ResourceFunction["SpanRange"][All ;; 3 ;; -1, 10]
Out[11]=
In[12]:=
ResourceFunction["SpanRange"][3 ;; All, 10]
Out[12]=
In[13]:=
ResourceFunction["SpanRange"][3 ;; All ;; -1, 10]
Out[13]=

All in the step position of a span chooses either to increment or decrement by 1:

In[14]:=
ResourceFunction["SpanRange"][3 ;; 7 ;; All, 10]
Out[14]=
In[15]:=
ResourceFunction["SpanRange"][7 ;; 3 ;; All, 10]
Out[15]=
In[16]:=
ResourceFunction["SpanRange"][All ;; 7 ;; All, 10]
Out[16]=
In[17]:=
ResourceFunction["SpanRange"][All ;; 3 ;; All, 10]
Out[17]=
In[18]:=
ResourceFunction["SpanRange"][10 ;; All ;; All, 10]
Out[18]=

UpTo is interpreted as an upper bound for the output range size:

In[19]:=
ResourceFunction["SpanRange"][4 ;; UpTo[3], 10]
Out[19]=

When necessary, a negative step is used to satisfy the input:

In[20]:=
ResourceFunction["SpanRange"][UpTo[3] ;; 2 ;; All, 10]
Out[20]=

A positive step is used when possible:

In[21]:=
ResourceFunction["SpanRange"][UpTo[3] ;; 5 ;; All, 10]
Out[21]=
In[22]:=
ResourceFunction["SpanRange"][All ;; UpTo[3], 10]
Out[22]=
In[23]:=
ResourceFunction["SpanRange"][UpTo[3] ;; All ;; All, 10]
Out[23]=
In[24]:=
ResourceFunction["SpanRange"][4 ;; UpTo[10] ;; All, 10]
Out[24]=
In[25]:=
ResourceFunction["SpanRange"][6 ;; UpTo[10] ;; All, 10]
Out[25]=
In[26]:=
ResourceFunction["SpanRange"][UpTo[4] ;; 6 ;; All, 10]
Out[26]=
In[27]:=
ResourceFunction["SpanRange"][UpTo[10] ;; 4 ;; All, 10]
Out[27]=

UpTo with negative size. Use Quiet to avoid messages from UpTo:

In[28]:=
ResourceFunction["SpanRange"][UpTo[-2] ;;, 10] // Quiet
Out[28]=
In[29]:=
ResourceFunction["SpanRange"][;; UpTo[-2], 10] // Quiet
Out[29]=

UpTo[0] generates different empty ranges:

In[30]:=
ResourceFunction["SpanRange"][UpTo[0] ;;, 10]
Out[30]=
In[31]:=
ResourceFunction["SpanRange"][UpTo[0] ;; ;; -1, 10]
Out[31]=
In[32]:=
ResourceFunction["SpanRange"][;; UpTo[0], 10]
Out[32]=
In[33]:=
ResourceFunction["SpanRange"][;; UpTo[0] ;; -1, 10]
Out[33]=
In[34]:=
ResourceFunction["SpanRange"][All ;; UpTo[0] ;; -1, 10]
Out[34]=

0 is allowed as left or right span position in order to index a Head of an expression:

In[35]:=
ResourceFunction["SpanRange"][0 ;;, 10]
Out[35]=
In[36]:=
ResourceFunction["SpanRange"][All ;; 0 ;; -1, 10]
Out[36]=
In[37]:=
ResourceFunction["SpanRange"][0 ;; UpTo[3], 10]
Out[37]=
In[38]:=
ResourceFunction["SpanRange"][0 ;;, 0]
Out[38]=

0 length expressions generate empty ranges:

In[39]:=
ResourceFunction["SpanRange"][UpTo[10] ;;, 0]
Out[39]=
In[40]:=
ResourceFunction["SpanRange"][All ;; UpTo[10], 0]
Out[40]=
In[41]:=
ResourceFunction["SpanRange"][All ;; UpTo[10] ;; -1, 0]
Out[41]=
In[42]:=
ResourceFunction["SpanRange"][UpTo[10] ;; ;; -1, 0]
Out[42]=

Infinity length may generate infinite ranges:

In[43]:=
ResourceFunction["SpanRange"][;; , Infinity]
Out[43]=
In[44]:=
ResourceFunction["SpanRange"][10 ;; ;; 2, Infinity]
Out[44]=

UpTo[Infinity] is the same as All:

In[45]:=
ResourceFunction["SpanRange"][UpTo[Infinity] ;; 4 ;; All, 10]
Out[45]=
In[46]:=
ResourceFunction["SpanRange"][4 ;; UpTo[Infinity] ;; All, 10]
Out[46]=

UpTo at both ends of the span chooses the minimum constraint:

In[47]:=
ResourceFunction["SpanRange"][UpTo[7] ;; UpTo[3], 10]
Out[47]=
In[48]:=
ResourceFunction["SpanRange"][UpTo[3] ;; UpTo[7] ;; All, 10]
Out[48]=
In[49]:=
ResourceFunction["SpanRange"][UpTo[3] ;; UpTo[7] ;; 1, 10]
Out[49]=
In[50]:=
ResourceFunction["SpanRange"][UpTo[3] ;; UpTo[7] ;; -1, 10]
Out[50]=

Inputs which are not an explicit Span:

In[51]:=
ResourceFunction["SpanRange"][UpTo[7], 10]
Out[51]=
In[52]:=
ResourceFunction["SpanRange"][-UpTo[7], 10]
Out[52]=
In[53]:=
ResourceFunction["SpanRange"][7, 10]
Out[53]=
In[54]:=
ResourceFunction["SpanRange"][{7}, 10]
Out[54]=
In[55]:=
ResourceFunction["SpanRange"][-7, 10]
Out[55]=
In[56]:=
ResourceFunction["SpanRange"][{-7}, 10]
Out[56]=
In[57]:=
ResourceFunction["SpanRange"][{-7, 9}, 10]
Out[57]=
In[58]:=
ResourceFunction["SpanRange"][{-7, 9, 2}, 10]
Out[58]=

Compose multiple spans together:

In[59]:=
ResourceFunction["SpanRange"][(2 ;;)/*(-2 ;; ;; -1), 10]
Out[59]=
In[60]:=
ResourceFunction["SpanRange"][(2 ;; ;; 3)/*UpTo[3], 10]
Out[60]=
In[61]:=
ResourceFunction["SpanRange"][(2 ;; ;; 3)/*(UpTo[3] ;; ;; -2), 10]
Out[61]=
In[62]:=
ResourceFunction[
 "SpanRange"][(2 ;; ;; 2)/*(;; UpTo[3] ;; 3), Infinity]
Out[62]=

Applications (1) 

Use SpanRange with Range to generate explicit part numbers for various computations:

In[63]:=
extract[expr_, span_] := Enclose@Extract[expr, List /@ Range @@ Confirm@ResourceFunction["SpanRange"][span, expr]]
In[64]:=
mapAt[f_, expr_, span_] := Enclose@MapAt[f, expr, List /@ Range @@ Confirm@ResourceFunction["SpanRange"][span, expr]]
In[65]:=
replacePart[expr_, span_ -> new_] := Enclose@ReplacePart[expr, new, List /@ Range @@ Confirm@ResourceFunction["SpanRange"][span, expr]]
In[66]:=
extract[{1, 2, 3, 4}, -2 ;;]
Out[66]=
In[67]:=
extract[{1, 2, 3, 4}, -2 ;; 0 ;; -1]
Out[67]=
In[68]:=
extract[{1, 2, 3, 4}, -UpTo[3]]
Out[68]=
In[69]:=
extract[{1, 2}, -UpTo[3]]
Out[69]=
In[70]:=
mapAt[f, {1, 2, 3, 4}, 2 ;; UpTo[2]]
Out[70]=
In[71]:=
mapAt[f, {1, 2, 3, 4}, -2 ;; UpTo[2] ;; -2]
Out[71]=
In[72]:=
mapAt[f, {1, 2, 3, 4}, 2 ;; 0 ;; All]
Out[72]=
In[73]:=
replacePart[{1, 2, 3, 4}, 0 ;; UpTo[2] -> x]
Out[73]=
In[74]:=
replacePart[{1, 2, 3, 4}, ;; ;; 2 -> x]
Out[74]=

Possible Issues (2) 

Invalid spans indexing beyond a given length result in Failure:

In[75]:=
ResourceFunction["SpanRange"][3 ;; 15, 10]
Out[75]=
In[76]:=
ResourceFunction["SpanRange"][15 ;; 1 ;; All, 10]
Out[76]=
In[77]:=
ResourceFunction["SpanRange"][-15 ;;, 10]
Out[77]=
In[78]:=
ResourceFunction["SpanRange"][;; -15, 10]
Out[78]=
In[79]:=
ResourceFunction["SpanRange"][UpTo[10] ;;, Infinity]
Out[79]=

UpTo with negative integer throws a message:

In[80]:=
ResourceFunction["SpanRange"][UpTo[-3], 10]
Out[80]=
In[81]:=
ResourceFunction["SpanRange"][UpTo[-10] ;; ;; 2, Infinity]
Out[81]=

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.4.0 – 22 August 2025
  • 1.3.0 – 08 March 2024
  • 1.2.0 – 27 September 2023
  • 1.1.0 – 10 May 2022
  • 1.0.0 – 18 April 2022

License Information