6
$\begingroup$

For this data:

dt = <|"a"-> <|"x"-> 1|>,"b"-> <|"y"-> 2|>,"c"-> <|"z"->3|>|>

It’s awkward when mapping the same function to multiple locations:

dt // Query[{"a" -> {"x" -> Framed}}]

When applying the same function at multiple sites, syntax gets long:

dt // Query[{"a" -> {"x" -> Framed}}] // Query[{"b" -> {"y" -> Framed}}]

In larger datasets the problem compounds. Is there a workaround for shortcuts like this:

dt // Query[{All -> {All -> Framed}}]

And also with Lists, and Span

dt // Query[{All -> {(1;;2) -> Framed}}]

as well as with hybrids of List and Associations.

PS - Even the nested parentheses are a pain for deeply nested data (we routinely deal with 6 levels or more), mitigated by this helper:

queryAt[seq__] := Query[Fold[Rule /* Reverse /* List, Reverse[{seq}]]];

eg

 queryAt["a", "x", Framed]
$\endgroup$
8
  • $\begingroup$ dt // Query[All, All, Framed] should work. $\endgroup$ Commented Jun 1, 2016 at 19:44
  • $\begingroup$ @JHM, only in the special case where it's mapped to All leaves, versus at specific branches, eg dt // Query["a", All, Framed] projects out the other branches. $\endgroup$ Commented Jun 1, 2016 at 20:09
  • $\begingroup$ MapAt[Framed, {"a", "x"}]@dt $\endgroup$
    – chuy
    Commented Jun 1, 2016 at 20:41
  • $\begingroup$ @chuy, I don't want to mention "x" explicitly. This will also work MapAt[Framed, {{"a", "x"}, {"b", "y"}}]@dt but need it to work across a Span or All keys at lower level. $\endgroup$ Commented Jun 1, 2016 at 20:46
  • $\begingroup$ @Kuba, help me rephrase Q if necessary, but it's not about dropping a bracket - queryAt does that. It's about substituting All or Span instead of named keys. $\endgroup$ Commented Jun 1, 2016 at 20:49

1 Answer 1

4
$\begingroup$

You can use Replace and Tuples to expand a Part specification in MapAt so it behaves as needed with Span.

expandedPart[rules__] :=
 Tuples[Replace[{Span[r__] :> Range[r], (t_ /; Head[t] =!= List) -> List[t]}] /@ {rules}]

This expands a Part specification.

expandedPart[1 ;; 3 ;; 2, All]
(* {{1, All}, {3, All}} *)

Now with MapAt

MapAt[Framed, expandedPart[1 ;; 3 ;; 2, All]]@dt

Mathematica graphics

or

MapAt[Framed, expandedPart[{"a", "c"}, All]]@dt

Mathematica graphics

Hope this helps.

$\endgroup$
1
  • $\begingroup$ @alancalvitti Note that relative from end specifications like -4;;-2 will work with the above but not open mixed relative from start and end like ;;-2 or 1;;-2. $\endgroup$
    – Edmund
    Commented Jun 2, 2016 at 0:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.