9
$\begingroup$

Suppose I define a table using

Table[n, {n, -n0, n0}]

(where n0 is some positive integer) but I want n not to take the value n=0. How to skip it in the list {n,-n0,n0} most efficiently?

$\endgroup$
  • $\begingroup$ Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Read the faq! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$ – user9660 Nov 7 '14 at 20:13
  • $\begingroup$ I would make the range separately, and remove the unwanted indices, then map the function to the result. Like this range = Range[-10, 10]; range = DeleteCases[range, 0]; f[#] & /@ range. There are many other ways to do this. $\endgroup$ – Nasser Nov 7 '14 at 20:21
  • $\begingroup$ Thank you both. Being new to Mathematica, I just don't understand yet very well the end of your suggestion "f[#] & /@ range". How would it look like with my "Table example"? $\endgroup$ – wondering Nov 7 '14 at 20:36
  • $\begingroup$ it would look like this Table[n, {n, range}] $\endgroup$ – Algohi Nov 7 '14 at 20:38
  • 1
    $\begingroup$ I used general function f. For your example, use # & /@ range instead. Or you can even do Table[If[n != 0, n, Sequence @@ {}], {n, -10, 10}] but this might not be as efficient. Not sure. Or if you want to use Table on range, see Algohi note above. $\endgroup$ – Nasser Nov 7 '14 at 20:40
6
$\begingroup$

Let's look at four fairly obvious ways of generating your table.

With[{m = 5}, Delete[Table[n, {n, -m, m}], m + 1]]
With[{m = 5}, Join[Table[n, {n, -m, -1}], Table[n, {n, m}]]]
With[{m = 5}, Join[Range[-m, -1], Range[m]]]
With[{m = 5}, Select[Range[-m, m], # != 0 &]]

All of these give

{-5, -4, -3, -2, -1, 1, 2, 3, 4, 5}

as expected. But their performance varies quite substantially. To show this, I first define a timer function.

timer = Function[form, First[AbsoluteTiming[form]], {HoldAll}];

Then time the table generators when they generating 10^7 elements.

With[{m = 5*^6},
  Column[{
    timer /@
      Hold[
        Delete[Table[n, {n, -m, m}], m + 1],
        Join[Table[n, {n, -m, -1}], Table[n, {n, m}]],
        Join[Range[-m, -1], Range[m]],
        Select[Range[-m, m], # != 0 &]]
  }]
] // ReleaseHold

The results are

results

You can see the first two methods are about the same and give mediocre performance. The third using Range is reasonably fast (because everything is done on packed arrays?). The last using Select is very slow (because it must compare each item in the list to zero).

$\endgroup$
  • $\begingroup$ Thanks for your wonderful answer. However, I added this line to your code: ...Hold[... DeleteCases[{Range[-m, m]}, 0],... to check the performence of Nasser's suggestion. It performs even quicker - the results are: {1.044790}, {1.396429}, {0.591002}, {19.907948}, {0.408931} $\endgroup$ – wondering Nov 7 '14 at 23:29
  • $\begingroup$ One more thing - I could not add the DeleteCases[{Range[-m, m]}, 0] as the last object in your code, after Select[Range[-m, m], # != 0 &]], because then it shows the list. I had to put it before. What to do in order to be able to put it on the last place, as I intended? $\endgroup$ – wondering Nov 7 '14 at 23:35
  • $\begingroup$ @Nasser Please check my comment above. $\endgroup$ – wondering Nov 7 '14 at 23:41
  • $\begingroup$ @wondering to add DeleteCase: With[{m = 5*^6}, Column[{timer /@ Hold[Delete[Table[n, {n, -m, m}], m + 1],Join[Table[n, {n, -m, -1}],Table[n, {n, m}]],Join[Range[-m, -1], Range[m]],Select[Range[-m, m], # != 0 &],range = DeleteCases[Range[-m, m], 0]; Table[n, {n, range}],range = DeleteCases[Range[-m, m], 0]; # & /@ range]}]] // ReleaseHold, then you'll get { {0.161521},{0.158520},{0.054507},{4.920125},{1.930245},{1.466686}} $\endgroup$ – Nasser Nov 8 '14 at 4:45
  • $\begingroup$ Delete[Range[-m, m], {m + 1}] seems to be faster than the alternatives considered. $\endgroup$ – kglr Nov 8 '14 at 4:45
2
$\begingroup$

Here's an alternative if you want to filter the indices (not the results). It's also a bit more flexible with the exclusions, accepting a list of them.

tableExcept[a_, iter__, except__] :=
  Table[a, Evaluate@{First@iter, Table[First@iter, iter] /. ((# -> Sequence[]) & /@ except)}]

tableExcept[f[n], {n, -3, 3}, {0}]
(*{f[-3], f[-2], f[-1], f[1], f[2], f[3]}*)

tableExcept[f[n], {n, -3, 3}, {-2, 0, 3}]
(*{f[-3], f[-1], f[1], f[2]}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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