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$ – user55405 Dec 9 '19 at 11:56
3
$\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} *)
    
| improve this answer | |
$\endgroup$
3
$\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}

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy