4
$\begingroup$

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?

$\endgroup$
8
  • 4
    $\begingroup$ ... but why?! What advantage do you expect from laboriously trying to subvert such a fundamental feature of the language? Can't you simply adjust your iterator? $\endgroup$
    – MarcoB
    May 26, 2015 at 16:48
  • $\begingroup$ ehm, use... python? $\endgroup$
    – gpap
    May 26, 2015 at 16:50
  • $\begingroup$ In physics, we often like to denote the zeroth component of a vector as the time component and then count the spatial components as $1,\cdots,d-1$. Since I have all my equations on paper in that form, it would have been convenient for me when doing calculations to directly type it in that form in Mathematica. I agree if this is not possible (or a good thing to do) then I can just go ahead and shift my iterator. This is not convenient for me though since in my head I always think of v[[1]] of being a spatial component whereas I would now have to think of it as a time component. $\endgroup$
    – Prahar
    May 26, 2015 at 16:51
  • 1
    $\begingroup$ Hmm, but then how should we denote the object's head if we index entries from 0? $\endgroup$ May 26, 2015 at 16:56
  • 1
    $\begingroup$ Perhaps you could use Association instead. $\endgroup$
    – Greg Hurst
    May 27, 2015 at 1:32

4 Answers 4

7
$\begingroup$

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

Mathematica graphics

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

Mathematica graphics

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.

$\endgroup$
3
  • $\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$
    – Prahar
    May 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$
    – Nasser
    May 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$
    – Prahar
    May 26, 2015 at 17:50
4
$\begingroup$

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.

$\endgroup$
1
  • 1
    $\begingroup$ NB This works for readonly lists. You can't set C subscript 1 = ... $\endgroup$ Nov 17, 2020 at 14:23
3
$\begingroup$

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.

$\endgroup$
0
$\begingroup$

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.