Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Suppose that I have the following sample list, called list:

list = {"bBb", "aAa", "aaa"};

Now suppose I want to select the elements that do not contain the string "A". One way to do this is to use Select with StringMatchQ:

Select[list, ! StringMatchQ[#, ___ ~~ "A" ~~ ___] &]

{"bBb", "aaa"}

(See, for example, this old question.)

But, instead of selecting the elements which do not contain "A", is it possible to use Select with StringMatchQ, but this time selecting all patterns except those that match the pattern ___ ~~ "A" ~~ ___. My thought is to use Except:

Select[list, StringMatchQ[#, Except[___ ~~ "A" ~~ ___]] &]

{}

StringExpression::invld: Element Except[___ ~~ "A" ~~ ___] is not a valid string or pattern element in StringExpression[Except[___ ~~ "A" ~~ ___]]

But I get the error message above. So I looked in the documentation for StringMatchQ. It has the following three general syntax forms:

StringMatchQ["string", patt]
StringMatchQ["string", RegularExpression["regex"]]
StringMatchQ[{s1, s2, ...}, p]

Thinking about the first form, StringMatchQ takes a pattern as its second argument. I know that ___ ~~ "A" ~~ ___ is a pattern, but is Except[___ ~~ "A" ~~ ___] a pattern? According to the documentation for Except, it is. The next question is, is Except[___ ~~ "A" ~~ ___] a string pattern? According to the error message above, it would seem not. (Also, apparently StringMatchQ takes only string patterns as its second argument -- which, of course, is logical.)

So, my overall question is, why does Select[list, StringMatchQ[#, Except[___ ~~ "A" ~~ ___]] &] give an error?

share|improve this question
    
I've found that Except is generally buggy with strings, which is why I always avoid it (with strings). For instance, compare: StringMatchQ["a", Except["b"]] and StringMatchQ["a", Except["bb"]] –  rm -rf Dec 28 '13 at 18:22
    
@rm-rf The StringExpression doc says: Except[p] - any character except ones matching p IMHO implying that p can only be a character in this context and not a string. Behavior is therefore documented and not a bug. –  Sjoerd C. de Vries Dec 28 '13 at 18:39
    
@SjoerdC.deVries Ah, good point. I forgot that StringMatchQ internally calls StringExpression on the second argument. That also explains OP's error then. You should post that as an answer. –  rm -rf Dec 28 '13 at 18:45
add comment

2 Answers

up vote 5 down vote accepted

When applied to string patterns Except only seems to work for string patterns that represent classes of characters or for string patterns that represent positions in strings, e.g.:

Except[{"A" | "B"}]
Except[WordCharacter]
Except[StartOfLine]

If you apply Except to an arbitrary String pattern (i.e., the head is StringExpression), the resulting expression does not seem to be a workable string expression. The documentation does not make this explicitly clear.

An alternate solution is to use StringFreeQ instead of StringMatchQ with Except:

Select[list, StringFreeQ[#, ___ ~~ "A" ~~ ___] &]

Also note that if the list is really large, using Pick in combination with the listable form of StringFreeQ is an order of a magnitude faster:

Pick[list, StringFreeQ[list, ___ ~~ "A" ~~ ___]]
share|improve this answer
add comment

The StringExpression doc says: Except[p]: any character except ones matching p. This seems to imply that Except[p] can only stand for a single character in this context and not a string.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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