6
$\begingroup$

I have some rows I want to put into a Grid:

rows = {{a, "foo"}, {b, "bar"}, {c, SpanFromAbove}, 
  {d, "baz"}, {e, SpanFromAbove}, {f, SpanFromAbove}, 
  {g, "quux"}};

In order to make it easier to read, I want to use alternating background colors, which I tried to do the standard way:

Grid[rows, Alignment -> {{Automatic, Left}, Center}, 
 Background -> {Automatic, {{LightYellow, LightBlue}}}]

However, what I get is this ugly mess:

an ugly mess

What I want looks like this:

a less ugly mess

In order to get that, though, I had to resort to a rather convoluted solution that explicitly inserts Items around elements to color them.

Module[{except = Except[SpanFromAbove], 
  colors = {LightYellow, LightBlue}, split, item}, 

 split = SequenceCases[rows, 
    seq:{{_, except}, {_, SpanFromAbove}...} :> 
     Map[Replace[x:except :> item[x]], seq, {2}]]; 

 Grid[Catenate[MapThread[
     #1 /. item[x_] :> Item[x, Background -> #2] & , 
     {split, PadRight[{}, Length[split], colors]}]], 
   Alignment -> {{Automatic, Left}, Center}]]

I could probably make this a bit less complicated with some elbow grease, but it would be really nice if I could somehow tell grid to have the colors alternate based on the spanned groups of rows and let it do the hard work.

Is there a way to do that?

Failing that, is there a really slick way to get the Items where I want them to go?

$\endgroup$
4
$\begingroup$
colors = {LightYellow, LightBlue};

rowclrs = Module[{col = colors}, 
   Last[col = If[# === SpanFromAbove, Identity, RotateLeft]@col] & /@ rows[[All, 2]]];

Grid[rows, Alignment -> {{Automatic, Left}, Center}, Background -> {Automatic,{rowclrs}}]

enter image description here

A lengthier alternative:

lengths = Length /@ Split[rows[[All, 2]], #2 === SpanFromAbove &];

rowclrs = Flatten @ 
   MapIndexed[ConstantArray[colors[[Mod[#2[[1]], Length @ colors, 1]]], #] &, lengths]

Grid[rows, Alignment -> {{Automatic, Left}, Center}, Background -> {Automatic, {rowclrs}}]

enter image description here

With both methods we can cycle through a longer list of colors. For example, with colors = {LightYellow, LightBlue, LightRed} we get

enter image description here

| improve this answer | |
$\endgroup$
3
$\begingroup$
rows = {{a, "foo"}, {b, "bar"}, {c, SpanFromAbove}, {d, "baz"},
        {e, SpanFromAbove}, {f, SpanFromAbove}, {g, "quux"}};

rowclrs =
  Module[{i = -1},
    i *= If[# === SpanFromAbove, 1, -1] & /@ rows[[All, 2]] //
      {LightYellow, LightBlue}[[#]] &
  ];

Grid[rows, Alignment -> {{Automatic, Left}, Center}, 
 Background -> {Automatic, {rowclrs}}]

enter image description here

| improve this answer | |
$\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.