3
$\begingroup$

I would like to be extend the below solution to be able to find get all rules from the list step[2] that match the generic pattern k_Digit_p. Where k and p are not generic characters but form part of the symbol name. Unfortunately I've stalled in my understanding of symbolic pattern matches, without converting the symbol names to strings. How can I define the generic pattern above without converting to strings and performing StringMatchQ[] test?

params={k1p,k1m,k2p,k2m,nfb,pfb};
step[1]={1.,1.,1.,1.,1.,1.};
parameterLimits={k1p->{0.25,1.5}};
step[2]=step[1][[#]]+RandomReal[{-1.,1.}]&/@Range[Length@params];
step[2]=Thread[params->step[2]]
k1p->0.0432604,k1m->0.898291,k2p->0.436556,k2m->0.917969,nfb->0.519343,pfb->1.00006}
Cases[step[2], PatternSequence[k1p -> _]]
{k1p->0.0432604}
$\endgroup$
0

3 Answers 3

4
$\begingroup$

I don't think you can avoid using strings, but that doesn't mean the output will contain strings.

Pick[step[2], StringMatchQ[ToString /@ step[2][[All, 1]], "k*p"]]
{k1p -> 1.09503, k2p -> 1.32185}
$\endgroup$
1
  • $\begingroup$ I see, converting to strings is still extremely fast so that will not be a problem. And having the output as an expression will make testing each element of the returning list of rules straight forward. $\endgroup$
    – tarhawk
    Commented Jul 22, 2015 at 14:34
3
$\begingroup$

I would use Cases with a condition and SymbolName.

Cases[step[2], (symbol_ -> _) /; StringMatchQ[SymbolName[symbol], "k*p"]]

Another solution:

step[2] /. (symbol_ -> value_) /; Not@StringMatchQ[SymbolName[symbol], "k*p"] :> Nothing

This solution makes use of Nothing which is new in Mathematica version 10.2. Nothing could be replaced by Sequence[] is earlier versions.

$\endgroup$
2
$\begingroup$

If you want to use a pattern, you could use

Cases[step[2],
  Alternatives@@HoldPattern/@Thread[ToExpression[Names["Global`k*p"]]->_Real]]

(* {k1p -> 1.5396, k2p -> 1.91751} *)

Technically this does not convert anything to strings, it just looks up all the user-defined names that match "k*p". It's not really elegant though.

Alternatively you can use Select as well:

Select[step[2], StringMatchQ[ToString[#[[1]]], "k*p"] &]

(* {k1p -> 1.5396, k2p -> 1.91751} *)
$\endgroup$

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