3
m = RandomInteger[{-5, 5}, {10, 10}];
m /. {x__, y_ /; y > 0} -> Style[{x, y}, Red]
% // TableForm

When m without style , TableForm or Grid works well on it. But when I set a style, it doesn't work as I expected. How can I fix the problem?

cormullion
  • 24,243
  • 4
  • 64
  • 133
expression
  • 5,642
  • 1
  • 19
  • 46
  • @andre, I'd suggest putting that as an answer – Simon Woods May 18 '13 at 21:30
  • 1
    As a matter of taste I would rewrite the replacement rule as m /. l_List /; Last[l] > 0 :> .... This formulation already hints at what is the problem with Style being applied to a list. – gwr May 19 '13 at 13:07

2 Answers2

10

Here is a solution :

m = RandomInteger[{-5, 5}, {10, 10}];
m /. {x__, y_ /; y > 0} :> (Style[#, Red] & /@ {x, y});
% // TableForm

Explanation about TableForm[]

TableForm[] accepts as argument only a List[] of List[].

m /. {x__, y_ /; y > 0} -> Style[{x, y}, Red] seems to be a List[] of List[] :

enter image description here

but in fact the red lines have a wrapper (Style[]) that indicates the color. Here is the InputForm of the same thing :

enter image description here

The solution is to wrap the color deeper in the expression with

m /. {x__, y_ /; y > 0} :> (Style[#, Red] & /@ {x, y}) :

It looks like nearly the same :

enter image description here

But this time we have a List[] of List[]. Here is the InputForm :

enter image description here

Small explanation about :> and not ->

My first attempt was to use :

m /. {x__, y_ /; y > 0} ->  (Style[#, Red] & /@ {x, y}  

with -> instead of :>

It didn't work.

The reason is the ordering of evaluation :

  • first Style[#, Red] & /@ {x, y} is evaluated.
    It becomes {Style[x, RGBColor[1, 0, 0]],Style[y, RGBColor[1, 0, 0]]}

  • then x is evaluated. With x=Sequence[1,2,3] for example, it gives

    Style[1, 2, 3, ... color informations ...]

    which is not a valid syntax for Style[]

andre314
  • 18,474
  • 1
  • 36
  • 69
5

As excellently described by andre the problem is that style is applied to the row vectors rather than the array elements themselves, and TableForm is not written to handle this situation. For ease of use you may wish to write a variant of Style that automatically threads over lists:

style[args__] := Thread[Style[args], List, 1]

Now:

m = RandomInteger[{-5, 5}, {10, 10}];
m /. a : {__, _?Positive} :> style[a, Red]
% // TableForm

Note the simpler pattern form, and the use of :> to localize the pattern name a.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371