8
$\begingroup$

Consider a string like:

str = "AabHHioPjggtYuggbwq";

I would like to have a function getpairs[x_String] that would extract for me:

getpairs[str]

{"Aa","HH","gg","gg"}

Any suggestions how to do this?

$\endgroup$
2
  • 2
    $\begingroup$ Could your input contain something like aaa? If so do you expect one or two aa in the result? (Or alternatively, if there's aAa, do you want both aA and Aa?) $\endgroup$ Commented Feb 14, 2017 at 16:24
  • $\begingroup$ Good point! I did not think about 3 letters yet. I guess if 3 appear, I would like to take them out separately. So, extract all occurrences of repeated letters (two or more). In your example: ...,"aaa",...,"aAa",..., $\endgroup$
    – Kagaratsch
    Commented Feb 14, 2017 at 16:41

3 Answers 3

17
$\begingroup$
str = "AabHHioPjggtYuggbwq";
StringCases[str, x_ ~~ x_, IgnoreCase -> True]

{"Aa", "HH", "gg", "gg"}

Or in the generalized version of the question:

str = "AaAbHHhhhioPjggtYuggGgGbwq";
StringCases[str, x_ ~~ (x_) .., IgnoreCase -> True]

{"AaA", "HHhhh", "gg", "ggGgG"}

$\endgroup$
8
  • 3
    $\begingroup$ After the OP's clarification in a comment on the question, I think this should be x_ ~~ x_ ... $\endgroup$ Commented Feb 14, 2017 at 16:43
  • $\begingroup$ Funny. :)This deserve 10 vote(include my one.)? $\endgroup$
    – yode
    Commented Feb 14, 2017 at 17:23
  • 1
    $\begingroup$ the generalized case needs parenthesis: x_ ~~ (x_) .. $\endgroup$
    – george2079
    Commented Feb 14, 2017 at 18:43
  • $\begingroup$ I'd generalize by allowing overlaps, at least that's how the question reads to me $\endgroup$
    – LLlAMnYP
    Commented Feb 15, 2017 at 5:31
  • 2
    $\begingroup$ @george2079 Not really, the space is sufficient. However, for some reason when copying the string without parenthesis into Mathematica, it just removes the space (if you reinserted manually it works). The worst part about that is that this short snippet doesn't survive a roundtrip transform out of and back into Mathematica. Maybe this should be reported as a bug... $\endgroup$ Commented Feb 15, 2017 at 13:26
5
$\begingroup$
getpairs[str_String] := StringJoin @@@ Select[
   Partition[Characters[str], 2, 1],
   SameQ @@ ToUpperCase[#] &]

str = "AabHHioPjggtYuggbwq";

getpairs[str]

(*  {"Aa", "HH", "gg", "gg"}  *)
$\endgroup$
6
  • $\begingroup$ Unfortunately, this doesn't generalise easily to the OP's comment on the question in the case of more than 2 consecutive occurrences of a letter. $\endgroup$ Commented Feb 14, 2017 at 16:43
  • $\begingroup$ @MartinEnder Well, we can't be expected to be prescient... $\endgroup$
    – C. E.
    Commented Feb 15, 2017 at 9:21
  • $\begingroup$ @C.E. No, but I think it's a good idea to think about edge cases the OP might be overlooking (or neglected to mention) and ask for clarification before answering. $\endgroup$ Commented Feb 15, 2017 at 13:25
  • $\begingroup$ @MartinEnder The title mentions "pairs", the name of the function in the question is "getpairs". So you would have us ask, "do you mean pairs?" I don't buy it. It's better to post the answer and wait for a reaction from OP, who may choose to request improvements if he wants. Needless to say, one should not post an answer if one does not understand the question. But both Bob and I got it right, as evidenced by the fact that my answer was accepted without the general case. $\endgroup$
    – C. E.
    Commented Feb 15, 2017 at 14:25
  • $\begingroup$ @C.E. Yes, the question says "pairs". Nevertheless, it was completely unclear what should happen to the input "aAa" (or whether the OP assumes that this case will never appear in the input). $\endgroup$ Commented Feb 15, 2017 at 14:29
5
$\begingroup$

I will give a RegularExpression version here.

str = "AabHHioPjggtYuggbwq";
StringCases[str, RegularExpression["(?i)(\\w)\\1"]]

{"Aa", "HH", "gg", "gg"}


Per this comment,that the string contain 3 or more letter case

str = "aAabHhHioPjggtYuggbwwq";
StringCases[str, RegularExpression["(?i)(\\w)\\1+"]]

{"aAa", "HhH", "gg", "gg", "ww"}

$\endgroup$
2
  • $\begingroup$ You can use \\1+ instead of \\1*\\1 (and it would be marginally more efficient to switch that around to \\1\\1* if you kept it). Also note that \\w matches more than just letters (but not all characters either). $\endgroup$ Commented Feb 15, 2017 at 13:28
  • $\begingroup$ @MartinEnder Wow,thanks for your advice. $\endgroup$
    – yode
    Commented Feb 15, 2017 at 13:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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