# How to build this grid with less code?

I have the diagonal and both upper and lower triangulars of a grid.

diag = {1, 2, 3, 4};
upper = {{u12, u13, u14}, {u23, u24}, {u34}};
lower = {{l21}, {l31, l32}, {l41, l42, l43}};


I want to combine this and display them in a grid with shading. My code for this is very bulky and I can't help feeling I've missed some function that would make more compact and easier to read. I also would rather not convert everything into Item to get the shading I want.

diag = Item[#, Background -> LightGray] & /@ diag;
upper = Map[Item[#, Background -> LightBlue] &, upper, {2}];
lower = Map[Item[#, Background -> LightGreen] &, lower, {2}];
first = Append[{diag[[1]]}, upper[[1]]] // Flatten;
mid = Table[Append[{diag[[row]]}] /* Append[upper[[row]]] /* Flatten@
lower[[row - 1]], {row, 2, 3}];
last = Append[lower[[3]], {diag[[4]]}] // Flatten;
Grid[Partition[{first, mid, last} // Flatten, 4]]


Is there a more compact way to do this?

(*Some pre-format, starting with your element definitions *)
diag = List /@ diag;
upper = Join[upper, {{}}];
lower = Join[{{}}, lower];

(*code *)
f[els_, col_] := Map[Item[#, Background -> col] &, els, {2}];
Grid@MapThread[Join, {f[lower, LightBlue], f[diag, LightGray], f[upper, LightRed]}]


• I like the combination method you have used. Sneaky to add an empty row and and nest the diagonal. Commented Nov 24, 2014 at 1:43

Generally speaking I favour using Grid options for styling rather than using Item. For example make your matrix:

MatrixForm[m = Array[Subscript[a, ##] &, {4, 4}]];


then:

Grid[m,
ItemStyle -> {None, None, Flatten@MapIndexed[Which[
#2[[2]] > #2[[1]], #2 -> Blue,
#2[[2]] == #2[[1]], #2 -> Gray,
#2[[2]] < #2[[1]], #2 -> Red
] &, m, {2}]}
]


Did you start with a matrix and then split it into upper, lower and diagonals? And if you did was that solely for the purpose of styling? If you did then just revert to your starting matrix. If somehow you actually only have the 3 components of the matrix then combine them simply like this:

m = RotateLeft@PadLeft[upper, {4, 4}] +


Or, as per @wreach answer, use negative indexes rather than wrapping to do the rotating:

m = PadLeft[upper, {-4, 4}] + PadRight[lower, {-4, 4}] + DiagonalMatrix[diag];


Then use the grid styling as before:

Grid[m, Background -> {None, None,
Flatten@MapIndexed[
Which[#2[[2]] > #2[[1]], #2 -> Blue, #2[[2]] == #2[[1]], #2 ->
Gray, #2[[2]] < #2[[1]], #2 -> Red] &, m, {2}]}]


• You aren't starting from the stated input. Was that on purpose? Commented Nov 24, 2014 at 1:28
• wanted to simply address using MapIndexed rather than Item for styling of Grid but will update Commented Nov 24, 2014 at 1:41
• Ah, using rules. Nice. I didn't realise the was possible but of course with MapIndexed. Commented Nov 24, 2014 at 1:42
• @Edmund I find it more intuitive doing it that way but it is up to individual preference Commented Nov 24, 2014 at 2:01

A helper function can reduce the boilerplate somewhat:

a_ // itemize[c_] := Map[Item[#, Background -> c]&, a, {-1}]

DiagonalMatrix[diag // itemize[LightGray]] +

• I like your answer ...although I've never liked using Item :) Commented Nov 24, 2014 at 2:07