0
$\begingroup$

Let's consider I have a list of rules:

{Aa -> 1/2, Av -> 2/5, Bx -> 3/7, Ce -> 4/9, ...}

I want to find all keys that contain the letter "A" and change their values to expressions. This means to have as a result:

***Some code here...***
{Aa -> ToExpression[1/2], Av -> ToExpression[2/5], Bx->3/7, Ce->4/9, ...}
$\endgroup$
  • 1
    $\begingroup$ if you are afraid of evaluation of Aa.., related: 75294 $\endgroup$ – Kuba Mar 26 '15 at 13:52
  • 2
    $\begingroup$ Your question implies that some or all the keys and values in your list are strings, but in your post they all look like symbols or rational numbers. Please reformat your example to make the strings explicit. $\endgroup$ – m_goldberg Mar 26 '15 at 14:42
6
$\begingroup$

I would use something like this:

Clear[f];
f[key_ -> val_] := key -> If[
   StringMatchQ[ToString@key, ___ ~~ "A" | "a" ~~ ___], q@val, val]

then

f /@ {Aa->1/2, Av->2/5, Bx->3/7, Ce->4/9}
(* {Aa -> q[1/2], Av -> q[2/5], Bx -> 3/7, Ce -> 4/9} *)

If you have v10, and your data is in an Association, you use AssociationMap, instead:

AssociationMap[f, <|Aa->1/2, Av->2/5, Bx->3/7, Ce->4/9|>
(* <|Aa -> q[1/2], Av -> q[2/5], Bx -> 3/7, Ce -> 4/9|> *)

An alternative to StringMatchQ, which I usually forget about, is StringFreeQ which simplifies the implementation:

Clear[g];
g[key_ -> val_] := key -> If[StringFreeQ[ToString@key, "A" | "a"], val, q@val]
$\endgroup$
  • 2
    $\begingroup$ There is StringFreeQ. $\endgroup$ – Kuba Mar 26 '15 at 14:44
  • $\begingroup$ @Kuba yep. That's one I usually forget exists. $\endgroup$ – rcollyer Mar 26 '15 at 15:39
4
$\begingroup$

A variation on the theme:

test = {Aa -> "1/2", Av -> "2/5", Bx -> "3/7", Ce -> "4/9"};

test /. (key_ /; 
     StringMatchQ[ToString[key], ___ ~~ "a" | "A" ~~ ___] -> 
    val_) :> (key -> ToExpression[val])

(*{Aa -> 1/2, Av -> 2/5, Bx -> "3/7", Ce -> "4/9"}*)
$\endgroup$
1
$\begingroup$

Try also this:

    as = <|"Aa" -> "1/2", "Av" -> "2/5", "Ca" -> "3/4", "Bx" -> "3/7", 
   "Ce" -> "4/9"|>;
ks = KeySelect[as, 
   Characters[#][[1]] == "A" || Characters[#][[2]] == "a" &];
op = Map[ToExpression, ks, 2];

Merge[{Association[Complement[Normal[as], Normal[ks]]], op}, Total]

yielding

    (*  <|"Bx" -> "3/7", "Ce" -> "4/9", "Aa" -> 1/2, "Av" -> 2/5, "Ca" -> 3/4|
 >   *)
$\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.