I suppose this is a trivial question to many of you, please bear with me.

  1. I have a long list of words, list1. I would like to "remove all words that contain a specific letter, say "o".

    list1 = {"world country", "capital", "population", "poppel”, "poppy"}
    DeleteCases[list1, "o" ∼∼ __]  (*does not work*)

I have tried many things and I have looked through many examples to no avail. I have read through Patterns but have not found anything that I can use. Several suggestions here refer to the case where the pattern is a word in the list, like so:

list1 = {"world country", "capital", "population", "popp", "poppy"}
DeleteCases[list1, "popp"]

(* Out: {"world country", "capital", "population", "poppy"} (*works*) *)

But this is not usable, as I need to have a pattern that means "all words that contain the letter "o")

  1. What I am really trying to solve is this: get rid of all words in list1 that contain the letters in list3, such as:

    list1 = {"world country", "capital", "population", "popp", "poppy"}
    list3 = {"o","q"}
    DeleteCases[list1, list3]  (*does not work*)
    (* My desired output would be {"capital"} *)
  • 1
    $\begingroup$ Take a look at StringFreeQ. $\endgroup$ – Kuba Feb 23 '16 at 14:55
  • $\begingroup$ Select[list1, StringContainsQ["o"]] $\endgroup$ – Jason B. Feb 23 '16 at 14:56
  • 1
    $\begingroup$ @Kuba, they forgot to include an operator form of StringFreeQ! $\endgroup$ – Jason B. Feb 23 '16 at 14:57
  • $\begingroup$ This is almost a duplicate 72670 but it was marked as a duplicate of more general question. $\endgroup$ – Kuba Feb 23 '16 at 14:57
  • 1
    $\begingroup$ @Jason, Not @*... I dunno what to say. Why not ! StringContainsQ["o"], if you're going that way? :P $\endgroup$ – J. M.'s ennui Feb 23 '16 at 15:02
list1 = {"world country", "capital", "population", "popp", "poppy"}
list3 = {"o", "q"}
Select[list1, Not@StringContainsQ[#, Alternatives @@ list3] &]  

(* Out: {"capital"} *)

Just to flesh out this answer a bit, and because timing things is fun, let's explore Martin's excellent suggestion of using StringFreeQ rather than Not@StringContainsQ in the Select expression.

In order to appreciate the difference, however, we need a longer word list: enter the SOWPODS word list, used by English-language Scrabble players outside of North America:

sowpods = 
 Import["http://www.freescrabbledictionary.com/sowpods/download/sowpods.txt", "List"][[3;;]];

(* Out: 267 751 *)

and time the difference, considering also that StringFreeQ can take a list of arguments, so Alternatives can also be removed:

rejectlist = {"o", "q", "a", "e"};

Select[sowpods, Not@StringContainsQ[#, Alternatives @@ rejectlist] &]; // RepeatedTiming
Select[sowpods, StringFreeQ[#, Alternatives @@ rejectlist] &]; // RepeatedTiming
Select[sowpods, StringFreeQ[#, rejectlist] &]; // RepeatedTiming

(* Out: 
{1.8, Null}
{0.61, Null}
{0.368, Null}

The most direct StringFreeQ approach handily wins.

  • 1
    $\begingroup$ @MartinBüttner - your golfing instincts can't stand the extra 20 bytes! $\endgroup$ – Jason B. Feb 23 '16 at 15:23
  • 1
    $\begingroup$ @JasonB Of course not. :P (It also seems more intuitive and potentially more efficient though.) $\endgroup$ – Martin Ender Feb 23 '16 at 15:24
  • $\begingroup$ @MartinBüttner That's an excellent point. I added timings to my answer. $\endgroup$ – MarcoB Feb 23 '16 at 18:07
  • $\begingroup$ @MartinBüttner another good point indeed. I also added the Alternatives-free version to the timing: it is quite a bit faster! $\endgroup$ – MarcoB Feb 23 '16 at 19:16
  • $\begingroup$ @Marco From 10.4, StringContainsQ is in C (see its new PrintDefinitions) and it has an operator form. Here are the three timings I get (in the same order as yours, and using the operator form for the first input): {0.475, Null}, {0.668, Null}, {0.428, Null}. $\endgroup$ – user31159 Mar 6 '16 at 16:08

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