Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I can convert an expression with the head of Times,for example, 12*12.5*13*13.5*14*14.5 to {12, 12.5, 13, 13.5, 14, 14.5} by using the code below:

ReleaseHold[HoldForm[12*12.5*13*13.5*14*14.5] /. Times -> List]

I have a list which contains a lot of such expressions,here is an example:

listSample={12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5}

I still want to convert all the heads Times to List,but I failed when tried to Map HoldForm to each listItem,because it alway evaluates first. Here is my code:

ReleaseHold[HoldForm[#] /. Times -> List]&/@listSample

I want to get this result:

{{12, 12.5, 13, 13.5, 14, 14.5},{12, 12.5, 13, 13.5, 14, 14.5},{12, 12.5, 13, 13.5, 14, 14.5},{12, 12.5, 13, 13.5, 14, 14.5},{12, 12.5, 13, 13.5, 14, 14.5},{12, 12.5, 13, 13.5, 14, 14.5}}

share|improve this question

4 Answers 4

up vote 11 down vote accepted

The listSample containing the lists of multiplications must at all times remain wrapped in something that prevents it from being evaluated. So even the mere input line with which you define listSample is not going to work.

When you Map a function onto listSample, the latter isn't wrapped the way it should be, so it gets evaluated. You can't use Map directly on things that you would like to keep unevaluated. Fortunately, you don't need Map in this case since you only want to replace Times by List.

So I'd suggest the following definition which makes the process re-useable:

SetAttributes[removeTimes, HoldAll]; 
removeTimes[list_] := ReleaseHold[Hold[list] /. Times -> List]

Now you can take your example list literally and wrap it in the above function:

removeTimes[
 {12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5, 
  12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5, 
  12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5}]

{{12, 12.5, 13, 13.5, 14, 14.5}, {12, 12.5, 13, 13.5, 14, 14.5}, {12, 12.5, 13, 13.5, 14, 14.5}, {12, 12.5, 13, 13.5, 14, 14.5}, {12, 12.5, 13, 13.5, 14, 14.5}, {12, 12.5, 13, 13.5, 14, 14.5}}

share|improve this answer
1  
Very useful, for instance if one does copy+paste of a row with numbers from Excel into Mathematica. –  b.gatessucks Jul 3 '12 at 7:48
data=HoldForm@{12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5,12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5, 2*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5};
data/.Times->List // ReleaseHold

gives

{{12, 12.5`, 13, 13.5`, 14, 14.5`}, {12, 12.5`, 13, 13.5`, 14, 14.5`}, 
 {12, 12.5`, 13, 13.5`, 14, 14.5`}, {12, 12.5`, 13, 13.5`,14, 14.5`},
 {12, 12.5`, 13, 13.5`, 14, 14.5`}, {12, 12.5`, 13, 13.5`, 14, 14.5`}}

EDIT: An alternative:

timesToList = Function[{list}, Unevaluated[list] /. Times -> List, HoldAll]
timesToList[{12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5}]
(* ==> {{12, 12.5, 13, 13.5, 14, 14.5}, {12, 12.5, 13, 13.5, 14, 14.5}} *)
share|improve this answer
    
wow,your code is concise,+1 –  withparadox2 Jul 3 '12 at 6:19

The value assigned listSample must be held unevaluated by some means or manipulation is not possible (as there is no Times present). There are several options for this:

  1. Hold

  2. Unevaluated

  3. SetDelayed (:=)

Of these SetDelayed is the most concise, so I will use that:

listSample := {12*12.5*13*13.5*14*14.5, 12*12.5*13*13.5*14*14.5};

Normally this is fully evaluated as soon as you call listSample:

listSample
{5.34398*10^6, 5.34398*10^6}

It is nevertheless stored internally in the unevaluated form. Because of this we can use Block to temporarily change the meaning of Times to List while this evaluation is taking place:

Block[{Times = List}, listSample]
{{12, 12.5, 13, 13.5, 14, 14.5},
 {12, 12.5, 13, 13.5, 14, 14.5}}

You could also access the unevaluated data with OwnValues or with my step evaluation function which I wrote for this purpose.

step[listSample] /. Times -> List // ReleaseHold

This approach would be useful if you needed to do a more complex replacement than you could do with Block, as would Hold or Unevaluated.


Also consider this:

Unevaluated[12*12.5*13*13.5*14*14.5] /. Times -> List
{12, 12.5, 13, 13.5, 14, 14.5}

Notice that no ReleaseHold is needed in this case as Unevaluated momentarily holds its argument, unlike Hold which does so until released.

share|improve this answer
    
When should we use Unevaluated as opposed to Hold? –  Michael Wijaya Jul 3 '12 at 6:52
    
@Michael specific to this application, or generally? –  Mr.Wizard Jul 3 '12 at 6:53
    
Generally. I know that Unevaluated dissolves after we pass it through a function, but are there other considerations to keep in mind? –  Michael Wijaya Jul 3 '12 at 6:55
    
I am just wondering if you have a rule of thumb to recognize when to use Hold as opposed to Unevaluated. –  Michael Wijaya Jul 3 '12 at 6:59
    
@Michael basically what you just outlined: use Unevaluated when you want it to "dissolve" after one use, otherwise use Hold. –  Mr.Wizard Jul 3 '12 at 7:03

Given the way you defined listSample, Mathematica evaluates the RHS before setting the value. To understand why this is the case, you may want to read the documentation for the standard evaluation procedure.

In[21]:= listSample
Out[21]= {5.34398*10^6,5.34398*10^6,5.34398*10^6,5.34398*10^6,5.34398*10^6,5.34398*10^6}

Before we can manipulate this list of products, we need to make sure that the RHS is not evaluated. Strictly speaking, Hold as opposed to HoldForm suffices as do not need pretty-printing.

In[22]:= listSample2=Hold@{12*12.5*13*13.5*14*14.5,12*12.5*13*13.5*14*14.5,12*12.5*13*13.5*14*14.5,12*12.5*13*13.5*14*14.5,12*12.5*13*13.5*14*14.5,12*12.5*13*13.5*14*14.5}
Out[22]= Hold[{12 12.5 13 13.5 14 14.5,12 12.5 13 13.5 14 14.5,12 12.5 13 13.5 14 14.5,12 12.5 13 13.5 14 14.5,12 12.5 13 13.5 14 14.5,12 12.5 13 13.5 14 14.5}]

Before I do any sort of manipulation, I find it useful to look at its FullForm:

In[23]:= FullForm@listSample2
Out[23]//FullForm= Hold[List[Times[12,12.5`,13,13.5`,14,14.5`],Times[12,12.5`,13,13.5`,14,14.5`],Times[12,12.5`,13,13.5`,14,14.5`],Times[12,12.5`,13,13.5`,14,14.5`],Times[12,12.5`,13,13.5`,14,14.5`],Times[12,12.5`,13,13.5`,14,14.5`]]]

Another useful representation is TreeForm:

In[24]:= TreeForm@listSample2

TreeForm of listSample2

Either way, we see that the heads Times we want to replace are all at level {2}. Apply is the built-in function which replaces head, so we can use

In[25]:= ReleaseHold@Apply[List,listSample2,{2}]
Out[25]= {{12,12.5,13,13.5,14,14.5},{12,12.5,13,13.5,14,14.5},{12,12.5,13,13.5,14,14.5},{12,12.5,13,13.5,14,14.5},{12,12.5,13,13.5,14,14.5},{12,12.5,13,13.5,14,14.5}}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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