4
$\begingroup$

Here's an example input list:

list = {SomeFunction[v1, arg -> "val"], 
  SomeFunction[v2, target -> "targetVal"], 
  SomeFunction[v3, arg -> "val", target -> "targetVal"]}

I want to extract the first argument of each function in the list which contains the argument target -> "targetVal". Example output:

list = {SomeFunction[v1, arg -> "val"], 
  "extractedVal" -> v2, 
  "extractedVal" -> v3}

Here's a naive way to achieve this:

list /. {SomeFunction[x_, target -> "targetVal"] -> ("extractedVal" -> x),
  SomeFunction[x_, arg -> "val", target -> "targetVal"] -> ("extractedVal" -> x)}

The problem with this approach is that one has to list all the variants of the function with different combinations of arguments, in order for ReplaceAll (/.) to work. How do I achieve the intended output by simply supplying the condition that the function must contain the required argument (multple arguments may be required)?

I'm trying to utilize Mathematica's ability to parse RTF files to extract elements containing certain styles, which are given as "arguments" in StyleBox function/objects. I will be extracting multiple items at once.

$\endgroup$
  • $\begingroup$ See BlankNullSequence (___): list /. SomeFunction[x_, ___, target -> "targetVal", ___] :> x $\endgroup$ – Lukas Lang Dec 9 '19 at 11:04
  • $\begingroup$ That is good if there's one required argument, but what if there's multiple? The order of the argument seems to matter. $\endgroup$ – WeavingBird1917 Dec 9 '19 at 11:56
4
$\begingroup$

Here are two approaches:

  • Using BlankNullSequence (___) and OrderlessPatternSequence:

    {
      f[x1, a -> 1, b -> 2],
      f[x2, b -> 2, a -> 1],
      f[x3, c -> 2, a -> 1, d -> 5, b -> 2, e -> 6],
      f[x4, e -> 5, b -> 2, c -> 2, a -> 1, d -> 3]
      } /. f[x_, OrderlessPatternSequence[___, a -> 1, ___, b -> 2, ___]] :> x
    (* {x1, x2, x3, x4} *)
    
  • Using Condition (/;):

    {
      f[x1, a -> 1, b -> 2],
      f[x2, b -> 2, a -> 1],
      f[x3, c -> 2, a -> 1, d -> 5, b -> 2, e -> 6],
      f[x4, e -> 5, b -> 2, c -> 2, a -> 1, d -> 3]
     } /. f[x_, opts__Rule] /; ({a, b} /. {opts}) == {1, 2} :> x
    (* {x1, x2, x3, x4} *)
    
$\endgroup$
4
$\begingroup$
list /. _[v_, opts : OptionsPattern[]] /; 
  FilterRules[{opts}, {target}] != {} :> "extractedValue" -> v

{SomeFunction[v1, arg -> "val"],
"extractedValue" -> v2,
"extractedValue" -> v3}

Alternatively, use the same replacement rule with Replace at level 1:

Replace[list, _[v_, opts : OptionsPattern[]] /; 
   FilterRules[{opts}, {target}] != {} :> "extractedValue" -> v, 1]

{SomeFunction[v1, arg -> "val"],
"extractedValue" -> v2,
"extractedValue" -> v3}

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