5
$\begingroup$

I have some assocations, containing a lot of data, lets say something like

<|"x"->{... big list ...},....|>

I would like to print these associations in a convenient and concise form, let's say:

x:[xMinValue,xMaxValue] (where xMinValue=Min[{..Big List...}]...)

For this purpose my idea was to use the Format command. Reading the official mma doc I have this example:

Format[f[x_?ListQ]] := "f[x], x:[" <> ToString[Min[x]] <> ", " <> ToString[Max[x]] <> "]"

For example:

f[Range[20]]]

f[x], x:[1, 20]

However, and this is my problem, I have no success with Association:

Format[<|"x"->x_?ListQ|>] := "x:[" <> ToString[Min[x]] <> ", " <> ToString[Max[x]] <> "]"

SetDelayed::write: Tag Association in MakeBoxes[Association[x_?ListQ],FormatType_] is Protected.

SetDelayed::write: Tag Association in Association[x_?ListQ] is Protected.

My question: how to define custom and pretty print of Association?

$\endgroup$
1
  • 1
    $\begingroup$ First, Association have the propertiy Protected, so you have to Unprotect them first. Second, Associations are atomic. Hence, pattern matching within Associations does not work. $\endgroup$ – Henrik Schumacher Nov 23 '17 at 15:51
3
$\begingroup$

Here's a closely related answer: 149668

MakeBoxes does not need to assign to Association in exchange for an overhead which usually is not a problem (see 39675)

Also, be extremely careful during pattern matching / calculations for formatting/typesetting. Your _?ListQ will evaluate content to confirm pattern even if the expression is somewhere inside Hold or something. Try Hold@<|"x" -> (Print[1]; {1, 2, 3})|>

Summing up, here's something to work with:

With[
  { safeNumListQ = Function[elem, NumericQ[Unevaluated[elem]], HoldAllComplete]
  }
, MakeBoxes[
    Association["x" -> x : {__?safeNumListQ}], fmt_
  ] := StringTemplate["\"x:[``, ``]\""] @@ MinMax[x]
]

In general you need to care about evaluation on MinMax stage too but here we already confirmed it is a numerical list and MinMax won't leak anything.

<|"x" -> {1, 2, 3}|>
Hold@<|"x" -> {1, 2, 3, Print[1]}|>
Hold@<|"x" -> {1, 2, 3}|>
Hold@<|"x" -> (Print[1]; {1, 2, 3})|>

enter image description here

Further reading:

$\endgroup$
1
  • $\begingroup$ Thanks for your expertise I will carefully read your post and improve my code. $\endgroup$ – Picaud Vincent Nov 24 '17 at 11:39
2
$\begingroup$

This could be a way to do it. Use it without any guarantees from my side.

Unprotect[Association];
format[x_List] := "<< Very long list that we do not want to see, honestly. >>";
format[x_] := x;
Association /: Format[a_Association] := 
 Row[{"\[LeftAssociation]", 
   Sequence @@ 
    Riffle[Rule @@@ Transpose[{Keys[a], format /@ Values[a]}], ", "], 
   "\[RightAssociation]"}]
Protect[Association];

Here some example to see the effect:

Association["Bli" -> 1, "Bla" -> Association["Blabla" -> {2, 3}], "Blubb" -> {4, 5}]
$\endgroup$
1
  • $\begingroup$ Great! That was the kind of solution I was looking for. Many thanks. I will just wait a little bit to see if another solution is proposed. $\endgroup$ – Picaud Vincent Nov 23 '17 at 16:17
1
$\begingroup$

Inspired by @HenrikSchumacher answer, here is my answer, that filters the Association type I want to print in a special way.

First I define this test, used to check association type:

MyAssocationQ[assoc_] := MatchQ[assoc, <|"x" -> _?ListQ|>]

For instance:

MyAssocationQ[<|"x" -> {-5, 2, 9}|>]

returns

True

however

MyAssocationQ[2017]
MyAssocationQ[<|"x" -> {-5, 2, 9},"y"->1|>]

return

False

False

Then, following Henrik approach, we have to Unprotect the Assocation symbol, and define

Unprotect[Association];

Association /: Format[assoc_Association /; MyAssocationQ[assoc]] := 
  "x:[" <> ToString[Min[assoc["x"]]] <> ", " <> 
  ToString[Max[assoc["x"]]] <> "]";

Protect[Association];

Then I get the expected behavior:

In[]= <|"x" -> {-5, 2, 9}|>

Out[]= x:[-5, 9]

and

In[]= <|"x" -> {-5, 2, 9}, "y" -> 5|>

Out[]= <|"x" -> {-5, 2, 9}, "y" -> 5|>

is unaffected and is the usual behavior.

$\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.