The first element in a list v
in Mathematica is denoted by v[[1]]
and subsequent ones are then v[[2]]
, v[[3]]
, ..., v[[n]]
where $n$ is the length of the list. I wish to start counting at 0 instead, i.e. the first element should be obtained as v[[0]]
and subsequent ones as v[[1]]
,v[[2]]
, ...,v[[n-1]]
. How can I tell Mathematica to do this consistently throughout the document?
4 Answers
Two possible options:
option 1
ClearAll[v]
Needs["Notation`"]
len = 5;
v = RandomReal[{0, 1}, len];
And now add notation to shift the indes
Notation[NotationTemplateTag[
Subscript[v, i_]] \[DoubleLongLeftRightArrow]
NotationTemplateTag[v[[(i_) + 1]]]]
The above looks like this in the notebook
And now use the subscripted version for the zero index:
{Subscript[v, 0], v[[1]]}
(* {0.313776, 0.313776} *)
Hence the Do
loop from zero
Option 2
For each list v
defined a v0
function
ClearAll[v]
v0[i_] := v[[i + 1]]
And when you want zero index, use v0
instead of v
len = 5;
v = RandomReal[{0, 1}, len];
Do[Print@v0[i], {i, 0, len - 1}]
I myself would not use either of these, since they confuse the code. I would just use Mathematica with 1
index as is and change the looping to account for this. But you can decide if these will work for you or not.
-
$\begingroup$ Thanks a lot! I seem to be getting lots of comments asking me to not implement this change and just use the standard Mathematica notation. Can you explain in what way that is better as opposed to doing what you suggest here?? Note that I'm not writing any sort of code at all. I'm simply going to perform some calculations such as integrals and matrix algebra. For this purpose, I really don't see the advantage of one over the other. Maybe I'm missing something. $\endgroup$– PraharMay 26, 2015 at 17:42
-
3$\begingroup$ @Prahar There is nothing wrong with using these options for small code. But I was thinking when the code gets larger, and you have many functions, it can get confusing if some code uses index 1 and another uses index 0. Also the
Notation
package option requires loading it each time. So this makes it harder to share code with others. But you try them and decide if these work for you. See this note on the subject. $\endgroup$– NasserMay 26, 2015 at 17:47 -
$\begingroup$ OK. Thanks. I'll try your option 1. Option 2 doesn't really work for me since I have lots and lots of lists. In any case I would like to learn by practice how it gets difficult using this. If it does, I'll switch to standard Mathematica notation. Thanks for your help. $\endgroup$– PraharMay 26, 2015 at 17:50
This is comparable to Option 1 from Nasser, but a bit simpler to implement. Try redefining the Subscript symbol to a function, i.e.
Subscript[a_,b_]:=a[[b+1]];
c=Range[10];
Enter c then "ctrl -" for the subscript shortcut then your index number. Execute to return the zero indexed list value. This get's the same simple input syntax as Nasser's answer without the extra package loading.
-
1$\begingroup$ NB This works for readonly lists. You can't set C subscript 1 = ... $\endgroup$ Nov 17, 2020 at 14:23
As another work around, you can create a function
idx[i_]:=i+1
and then say
v[[idx[0]]]
This is similar to indirect addressing.
Also, if it's not important to be able to treat the objects as arrays, you can simply do something like
v[0] = something
where the single [bracket]
sets a DownValue.
Index-from-0 may have semantic value, not just be stylistic preference. You can turn it into an association:
my1BasedList = {"zero", "one", "two"}
v = AssociationThread[ Range[0, Length[my1BasedList] - 1],
my1BasedList]
v[0]
Output
{zero,one,two}
<|0->zero,1->one,2->two|>
v[0]
as [[Parts]] it is still 1-based : v[0] == v[[1]] (* True *)
By 'has semantic value' I mean, sometimes the index itself has a meaning. If it's a distance or a timestep, 0 may by the 'correct' starting point
v[[1]]
of being a spatial component whereas I would now have to think of it as a time component. $\endgroup$Association
instead. $\endgroup$