9
$\begingroup$

Suppose I have Association

testAssoc=Association[a->Association[1->1,2->2],b->Association[1->1,2->2]]

which pattern match this Association?

PS: of course MatchQ[testAssoc, _Association] return true, but I want to match ONLY nested Associations

$\endgroup$
  • 6
    $\begingroup$ An Association is an atom in Mathematica, so formally it has no deeper structure. It is not even an expression with head Association and some arguments; the command MatchQ[testAssoc, Association[___]] returns False. So I think the best you can do is first to use functions like Normal or Values: MatchQ[Values[testAssoc], {__Association}]] returns True. $\endgroup$ – Fred Simons Oct 8 '14 at 11:47
  • 1
    $\begingroup$ In 10.4 you can match within Associations. $\endgroup$ – masterxilo Jun 28 '16 at 21:45
12
$\begingroup$

Currently pattern - matcher doesn' t go inside an Association, and _Association is an exception (head test). You can note, for example, that an Association is AtomQ (although this is only a consequence of that). So, if you want to use pure patterns, you're currently out of luck. But, you can use recursive patterns. In this case:

nestedAssocPattern = assoc_Association /; MemberQ[Values[assoc], _Association]

Now, you can test:

MatchQ[testAssoc, nestedAssocPattern]

(* True *)

MatchQ[<|1 -> 2|>, nestedAssocPattern]

(* False *)
$\endgroup$
  • $\begingroup$ The pattern should be assoc_Association /; MatchQ[Values[assoc], {__Association}], I believe; the current form will match <|1 -> <|"a" -> 3, "b" -> 4|>, 2 -> 5|>, which I believe is not wanted. $\endgroup$ – J. M. is away Jun 4 '16 at 0:01
  • $\begingroup$ @J.M. You may be right, but the question does not give enough information to be sure. $\endgroup$ – Leonid Shifrin Jun 4 '16 at 8:43
6
$\begingroup$

With 10.4 you can use KeyValuePattern, or you can do it directly with a condition.

This gives elements whose keys are Associations:

Cases[{<|a -> <|1 -> 1|>, b -> <|2 -> 2|>|>, <|a -> <|1 -> 1, 2 -> 2|>, c -> 4|>}, 
    x_Association /; Union[Head /@ Values@x] == {Association}, {1}]

(* {<|a -> <|1 -> 1|>, b -> <|2 -> 2|>|>}  *)
$\endgroup$
  • $\begingroup$ It will also match <|b -> <|1 -> 1, 2 -> 2|>, c -> 1|> which is not nested association in this context. $\endgroup$ – Kuba Jun 3 '16 at 5:52
  • $\begingroup$ So he wants a pattern that matches associations where all keys are associations, right? $\endgroup$ – M.R. Jun 3 '16 at 19:09
  • $\begingroup$ I think so, but I'm not 100% sure :-/ $\endgroup$ – Kuba Jun 3 '16 at 19:17
  • $\begingroup$ @M.R., beware that KeyValuePattern only matches the first matching Key-Value rules in an Association and will not match subsequent ones. That behavior is at odds with replacement in Lists, eg if the Association is Normalized to a List. $\endgroup$ – alancalvitti Jan 9 '17 at 19:47
4
$\begingroup$

As already pointed out by others Association objects are presently not traversed by pattern matching.

See:

My interpretation of your question is that you want to test to see if all values in the top Association are themselves Associations, rather than testing if only one value is, which is what kguler and Leonid answered. Therefore I propose:

asc_Association /; MatchQ[Values[asc], {__Association}]

This checks that entire expression and all of its values are Associations.


One could almost use this Condition instead of MatchQ: AllTrue[asc, AssociationQ] except that:

AllTrue[<||>, AssociationQ]
True
$\endgroup$
0
$\begingroup$

Perhaps

foo=!FreeQ[#,_Association,1]&;

testAssoc=Association[a->Association[1->1,2->2],b->Association[1->1,2->2]];
testAssoc2=Association[a->aa,b->bb];
testAssoc3=List[a->Association[1->1,2->2],b->Association[1->1,2->2]];

foo/@{testAssoc,testAssoc2,testAssoc3}
(* {True, False, False} *)
$\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.