5
$\begingroup$

I have a list. I want to get all the elements in that list which do not match a given pattern. That is, I want the strings which do not match any of the following patterns:

  1. First and last characters are the same: $123aw1$
  2. Does not have two consecutive similar characters: $1era22we, awe33rt, 123aa123$

I wrote following code

inputset = ToString /@ {
  11223434, 12123434, 11234342, 11234243, 11234234, 11232434, 12132434, 
  12134234, 11234324, 11232443, 11234423, 12134243, 12314234, 12314324, 
  12341234, 11223344, 11223443, 11234432
};
outputset = Complement[inputset, 
  Select[inputset, 
    StringMatchQ[#, StringExpression[x_, ___, x_]] || 
      StringMatchQ[#, StringExpression[___, x_, x_, ___]] &]];

and I got

outputset = {12123434, 12132434, 12134234, 12134243, 12314234, 12314324, 12341234}

Is there an easy simple and efficient way to do this?

$\endgroup$
5
  • 3
    $\begingroup$ Why not just negate your pattern in Select with !(PATTERN)? $\endgroup$
    – gpap
    Commented Sep 17, 2013 at 15:15
  • 3
    $\begingroup$ Did you take a look at Except? $\endgroup$ Commented Sep 17, 2013 at 15:17
  • 2
    $\begingroup$ @JacobAkkerboom Except is pretty limited on string patterns, it only works on one character. You can't use it like: StringMatchQ[{"abc","xyz"}, Except["abc"]] $\endgroup$
    – ssch
    Commented Sep 17, 2013 at 15:32
  • $\begingroup$ What is the measure of similarity for "two consecutive similar characters"? $\endgroup$
    – m_goldberg
    Commented Sep 17, 2013 at 15:49
  • $\begingroup$ I mean same character appear at position "i" and position "i+1" of given string. "i" can be any position. So I don't want string like "1123", "23345","145aa". Also I don't want string which has same character at beginning and end like "a12wea", "12w33qw1", "2ert442" $\endgroup$
    – Vajira
    Commented Sep 17, 2013 at 16:35

2 Answers 2

6
$\begingroup$
Select[inputset, Not@(StringMatchQ[#, x_ ~~ __ ~~ x_] || 
                      StringMatchQ[#, ___ ~~ y_ ~~ y_ ~~ ___]) &]

I'm always suspicious about the use of Alternatives[] in string patterns, but in this case it seems to work. So you may also write a more compact form:

Select[inputset, ! StringMatchQ[#, (x_ ~~ __ ~~ x_)  | ( ___ ~~ y_ ~~ y_ ~~ ___)] &]

Note the need for parenthesizing.

$\endgroup$
5
$\begingroup$

Using Pick:

Pick[
  inputset,
  StringMatchQ[inputset, (x_ ~~ __ ~~ x_) | (___ ~~ y_ ~~ y_ ~~ ___)],
  False];
$\endgroup$

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.