4

If I have a list of numbers like this:

list = {0.3565127, 0.8656421, 0.231479879, 0.39698787, 0.536987651},

which are all between 0 and 1, each having lots of digits, and whose precision is not known (and also not important). I don't know their exact values. (It could be a list of hundreds of numbers, so we don't know each of them exactly).

Yet I know some of them have the form 0.?969?????????, where the ?s represent digits I do not know; besides; the digits known are all within the first five digits behind the decimal point.

So, how can I construct a pattern object (like x_^2 for symbols) for replacing numbers that match the pattern?

User18
  • 882
  • 4
  • 12

2 Answers2

4

It seems that OP wants a pattern object for use in replacement rules, so this does the trick,

{0.969, 0.0969, 0.00969, 0.3565127, 0.8656421, 0.231479879, 
  0.39698787, 0.536987651} /. 
 a_ /; MatchQ[
    First[RealDigits[a, 10, Automatic, -1]], {_, 9, 6, 9, __}] -> 4
(* {0.969, 4, 0.00969, 0.356513, 0.865642, 0.23148, 4, 0.536988} *)

edit Thanks as always to @J.M. for helping me write better Mathematica code.

Jason B.
  • 68,381
  • 3
  • 139
  • 286
2

Inspired by Jason B:

Select[list,
  MatchQ[
    TakeDrop[
      If[Negative[#2], ArrayPad[#1, {Abs[#2], 0}], #1], 
      Clip[#2, {0, \[Infinity]}]
    ] & @@ RealDigits[#] &, 
    {{}, {_, 9, 6, 9, __}}
  ] &
]
{0.396988}

Where the first list in patterns specifies the pattern for digits on the left side of the decimal point and the second for those on the right.

For earlier versions TakeDrop can be replaced with Through[{Take, Drop}[##]] &


Old answer

Not exactly pattern matching, but working:

Select[
 list,
 Mod[Floor[# 10^4], 10^3] == 565 &
]
{0.356513}

Same approach, slightly modified:

Pick[
   list,
   Mod[Floor[list 10^4], 10^3],
   565
]

Probably slower string approach:

StringCases[
  ToString[#, InputForm] & /@ list,
  StartOfString ~~ _ ~~ "." ~~ Repeated[_, {2}] ~~ "65" ~~ __ ~~ EndOfString
] // Flatten // Map[ToExpression]
{0.356513}

or, matching your question the best:

Cases[
    ToString[#, InputForm] & /@ list,
    _?(StringMatchQ[#, RegularExpression[".\\...698.*"]] &)
] // Flatten // Map[ToExpression]
{0.396988, 0.536988}
Kuba
  • 136,707
  • 13
  • 279
  • 740
  • @garej no because there the _ is repeated exactly twice. – Kuba Feb 23 '16 at 09:53
  • @Kuba Thank you! Yes it is an equally good alternative. Oh, but is there a convenient method in Mathematica to form a pattern object in such cases? What I have in mind is things like wild cards within the numbers, like this: 0.*565****..., where the * is a wild card. – User18 Feb 23 '16 at 10:00
  • @User18 take a look at the last on I've just edited. – Kuba Feb 23 '16 at 10:01
  • @Kuba, I see, by the way, how to avoid ToExpression to round up the string number? – garej Feb 23 '16 at 10:03
  • @garej rounding is done by the interface, if you take a look at FullForm or cell expression, you will see all is there. You can change number of displayed digits somewhere in preferences. Moreover, ToString respects that so I had to use InputForm. – Kuba Feb 23 '16 at 10:05
  • @Kuba, may be I'm missing something but 787 or 878? – garej Feb 23 '16 at 10:07
  • @garej could you elaborate? – Kuba Feb 23 '16 at 10:08
  • @Kuba Ah, I didn't refresh my web page just now. Thank you. The new code looks less simple than the first method, but I see now what is required to do it in Mathematica. – User18 Feb 23 '16 at 10:11
  • @User18 Yes, but is more flexible, e.g. you can use ".\\...6.8.*" regex while with first method you would have to check specific digits – Kuba Feb 23 '16 at 10:12
  • The question states that we do not know how many ?. Does it concern only ? after the pattern? If so, it is better to reformulate the question in this respect. – garej Feb 23 '16 at 10:12
  • @garej The question states "I don't know how many digits these numbers have." not how many are behind ?. – Kuba Feb 23 '16 at 10:13
  • @Kuba, but your string example with 698 found pattern after ??. Why not more or less? Select and Pick return nothing with 698... – garej Feb 23 '16 at 10:17
  • The numbers are all between 0 and 1, each having many, many digits, but the precision I do not know, and it is I think irrelevant. I'll edit my post to make it clearer. – User18 Feb 23 '16 at 10:21
  • 1
    @garej Select and Pick are aiming in ?,?565?... while the last one is looking for ?,??698?.... Where by ?... I mean repeated ? and by , I mean decimal point. – Kuba Feb 23 '16 at 10:21
  • @Kuba - this is trickier than it should be :-) If you try the Select above on the list {0.969, 0.0969, 0.00969, 0.3565127, 0.8656421, 0.231479879, 0.39698787, 0.536987651} it only catches one – Jason B. Feb 23 '16 at 10:56
  • Thank you @Kuba, your answers are really helpful! – User18 Feb 23 '16 at 11:42