18
$\begingroup$

% refers to the result of the preceding calculation (preceding in time) but this seems not necessarily to be the cell just above a given cell.

How can one refer to the result of the cell just above ?

$\endgroup$
3
  • 1
    $\begingroup$ You can use the index of the output to refer to it. For example, if it's Out[32] you can refer to it by %32. $\endgroup$
    – xzczd
    Feb 4, 2014 at 11:10
  • $\begingroup$ yes, but that number seems also to depend on the order I evaluate cells (which is not necessarily from top to bottom) and it also changes when evaluate a cell a second time (e.g. after changing something) $\endgroup$ Feb 4, 2014 at 11:35
  • 1
    $\begingroup$ Yeah, the number depends on the evaluation order. If you need to use the output of a specified cell for times, it's better to give a name to it. $\endgroup$
    – xzczd
    Feb 4, 2014 at 11:47

4 Answers 4

18
$\begingroup$

You can use something like this. (I have added extra steps to demonstrate practical usage.)

enter image description here

Selectable code

x = 3

y = x + 2;
Clear[x, y, z]
SelectionMove[EvaluationNotebook[], Previous, Cell, 3];
z = ToExpression@First@NotebookRead[EvaluationNotebook[]];
y + z

Addendum

Further to xzczd's comment, you can also use a cell tag :-

enter image description here

$\endgroup$
3
  • $\begingroup$ great ! It looks like one can even define a 'function' prevCell := Module[{}, SelectionMove[...]; Return[ToExpression@...];] $\endgroup$ Feb 4, 2014 at 12:06
  • 2
    $\begingroup$ (+1) Current implementation SelectionMove[EvaluationNotebook[], Previous, Cell, 3]; fails when the evaluation cell has already printed some output(s). More reliable approach would be SelectionMove[EvaluationNotebook[],Before,EvaluationCell]; SelectionMove[EvaluationNotebook[],Previous,Cell,1];. $\endgroup$ Feb 4, 2014 at 12:16
  • $\begingroup$ @AlexeyPopkov - Yes, that works nicely. $\endgroup$ Feb 4, 2014 at 13:15
15
$\begingroup$

Version 9 offers a couple of new ways to access cells that are useful to meet the needs of this question.

The first way involves the use of the Cells and EvaluationCell functions. They can be used in the present context like this:

previousCell[] :=
  Cells @ EvaluationNotebook[] /. {___, prev_, EvaluationCell[], ___} :>
    ToExpression @ First @ NotebookRead @ prev

Here, we retrieve all cells from the evaluation notebook and use pattern matching to find the cell prior to the currently evaluating cell. Having recovered that cell object, we extract its box representation and convert it to an expression. Proper error- and boundary-checking are left as exercises for the reader. This method's use of pattern-matching can be helpful if more elaborate conditions are needed to identify the sought cell.

A second approach is to use the undocumented function Experimental`ToCellIndex and its companion Experimental`FromCellIndex:

previousCell2[] :=
  ToExpression @ First @ NotebookRead @
    Experimental`FromCellIndex[Experimental`ToCellIndex @ EvaluationCell[] - 1]

The index of the evaluating cell is recovered using FromCellIndex, decremented, and then converted back to a cell object using ToCellIndex. The cell contents are then extracted using the same method as in previousCell. This method is more direct in that it operates upon cell indices, but lacks the flexibity of the earlier pattern-matching approach. Also, these experimental functions simply use Cells internally, so they do not offer any speed-up over direct use of that function.

screenshot of sample use

Edit

As @Jacob Akkerboom notes in the comments, the Experimental package has more cell helper functions. Of particular interest is Experimental`PreviousCell[] which, by default, returns the cell immediately prior to the evaluation cell, i.e. exactly what is requested by this question (how did I miss that in my initial response?). The full signature of that function is essentially equivalent to:

Experimental`PreviousCell[cell_CellObject:EvaluationCell[], style_:All, n_Integer:1]

cell is the reference cell. style names the style of cells to consider when counting, with All meaning all styles. n is how many cells to count backwards to locate the target cell. There is also Experimental`NextCell[] which operates in similar fashion but in the forward direction.

The implementations of Experimental`NextCell and Experimental`PreviousCell (and the other experimental cell functions) are all based upon the Cells function.

$\endgroup$
2
  • $\begingroup$ Great :) thanks for the latter but also for the neat former one because I was doing it in more complex way, till now. $\endgroup$
    – Kuba
    Feb 5, 2014 at 7:20
  • 1
    $\begingroup$ Maybe Experimental'NextCell can be useful. You can remove its attribute ReadProtected and use Information to see how it works (which is also the case for FromCellIndex and ToCellIndex ). $\endgroup$ Feb 12, 2014 at 11:35
5
$\begingroup$

Just for completeness, PreviousCell and NextCell were promoted to System` functions in version M10. For example:

enter image description here

$\endgroup$
2
$\begingroup$

All of the answers above assume that the output can be once again be made into a Mathematica statement by relying on the function ToExpression, which is not always the case (for instance when custom formatting rules are applied or custom objects exist).

I've created a solution that relies figures out what is the Out[] of the cell directly above and runs it, which can be easily achieved by

« := Out[
  ToExpression[
   StringCases[
     ToString[
      PreviousCell[CellStyle -> "Output"] // NotebookRead // Last],
     "Out[" ~~ d : DigitCharacter .. ~~ "]" :> d][[1]]
   ]
  ]

Here's a brief description of what's happening.

ToString[PreviousCell[] // NotebookRead // Last] returns a string containing the last entry of the previous cell object, which has the format "CellLabel -> Out[XXX]=" where "XXX" is the number of the output. Then, using StringCases[] I isolate this number, turn it into an integer with ToExpression[] and finally ask Out[] to give me the output of that cell.

Finally, I assign this function to the symbol « as it is conveniently placed on my keyboard, but feel free to re-assign it somewhere else.

$\endgroup$
4
  • $\begingroup$ If somebody knows a way of extending the function PreviousCell to give the n-th previous cell, do let me know, so that I can extend this to «[n] where n is the n-th cell above. Bonus points if you figure out how to bind this to ««, «««, etc. $\endgroup$ Feb 25 at 21:48
  • $\begingroup$ Nice. Perhaps Do[NotebookFind[EvaluationNotebook[], "Output", Previous, CellStyle, AutoScroll -> False], 3]; NotebookRead[EvaluationNotebook[]] for reading the 3rd previous output cell. — As for assumptions, note that Out[XXX] is not always defined (finite $HistoryLength or kernel restarted are common reasons). — Finally, ToExpression@StringTrim[CellLabel /. Options@ NotebookRead@ PreviousCell[CellStyle -> "Output"], "="] is another way to get the Out[XXX] expression. $\endgroup$
    – Goofy
    Feb 25 at 22:02
  • $\begingroup$ Trying to run the command that you suggested to get the 3d previous output cell does not seem to work, it gives a lot of output and the information about the cell directly above seems incorrect, or at least the Out number. As for assumptions, yes it will break in those situations, maybe raising a warning would be useful. $\endgroup$ Feb 26 at 21:44
  • $\begingroup$ Well, the code gets the 3rd previous output cell for me. I don't know why it doesn't work in your notebook. $\endgroup$
    – Goofy
    Feb 26 at 23:13

Your Answer

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

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