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$
  • 3
    $\begingroup$ Why not just negate your pattern in Select with !(PATTERN)? $\endgroup$ – gpap Sep 17 '13 at 15:15
  • 3
    $\begingroup$ Did you take a look at Except? $\endgroup$ – Jacob Akkerboom Sep 17 '13 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 Sep 17 '13 at 15:32
  • $\begingroup$ What is the measure of similarity for "two consecutive similar characters"? $\endgroup$ – m_goldberg Sep 17 '13 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 Sep 17 '13 at 16:35
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, privacy policy and cookie policy

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