2
\$\begingroup\$

I am doing some exercises in this book. I've been trying to avoid Regex so far in my mission to teach myself computer science, as it makes my head hurt. That said - one of the exercises is to find all words without the letter 'e'.

I have:

/\b([^e ]+)\b/

There must be a better way using Regex to find all words that don't contain a certain character.

Here is an example:

toMatch = /\b([^e ]+)\b/;
testArr = ["platypus", "elvis", "javascript", "stackoverflow"];

for (str in testArr)
  console.log(testArr[str] + " has no e -> " + toMatch.test(testArr[str]));

\$\endgroup\$
  • 1
    \$\begingroup\$ for...in should not be used to iterate over an array. \$\endgroup\$ – Kruga Dec 19 '16 at 8:50
4
\$\begingroup\$

While using regex, yours is probably the most simple. Just make sure you set the g flag in other languages:

https://regex101.com/r/zJ0H2k/2

If you know about regex in unnecessary complexity you can use look behinds and such:

/(?:^|(?<= ))([^e ]+)(?:\n|(?= )|$)/g

https://regex101.com/r/cM9hD8/1

you can make your regex as complicated as possible, I think that your answer is a good answer just in terms of the length of the regular expression.

\$\endgroup\$
5
\$\begingroup\$

If just looking for a single character in a set of strings, I would think basic string manipulation would be sufficient.

What is not clear to me from your question is why you are using word boundaries in your regex definition when the array itself is just single words. Is your intent to analyze individual words in each of the array strings (with string perhaps consisting of multiple words) or are you only truly going to have single word string in the array?

For now, I will provide answer given the assumption of an array of single words.

To do that, I would simply use Array.filter() in combination with String.indexOf().

var needle = 'e';
var haystack = ["platypus", "elvis", "javascript", "stackoverflow"];
var filtered = haystack.filter( str => (str.indexOf(needle) === -1) );

Based on your comment that array entries could have multiple words, I would suggest using Array.reduce() to build all array of all words across all entries that do not have have the needle character in them.

var needle = 'e';
// note global flag here to get all matches
var regex = new RegExp('\\b([^' + needle + ']+)\\b', 'g');
var haystack = ["platypus", "elvis", "javascript", "stackoverflow", "some multi-word string"];
var result = haystack.reduce(
    (aggregator, str) => {
        while (match = regex.exec(str) !== null) {
            aggregator.push(match[1]);
        }
    },
    []
);
console.log(result); // ["platypus", "javascript", "multi-word", "string"]
\$\endgroup\$
  • \$\begingroup\$ Hi Mike, thanks for your answer. I am trying specifically to do this in regex (from eloquentjavascript.net/09_regexp.html). In answer to your question; the examples given in the book have arrays with multi-word elements. \$\endgroup\$ – Aidenhjj Dec 16 '16 at 17:54
  • \$\begingroup\$ @Aidenhjj I have updated my answer to consider search within multi-word strings in the array. \$\endgroup\$ – Mike Brant Dec 16 '16 at 18:34
5
\$\begingroup\$

I tried

/\b[^e]+\b/i

for the first time too, but the problem with it, is that it also returns true to inputs such as "444fortyfortyfour", where there are digits in the word.

The book says:

  1. A word without the letter e (or E)

I had come up with the following solution:

let regExp = /\b[a-df-z]+\b/i

regExp.test("Anything")
// true

regExp.test("Except 'e'")
// false

regExp.test("0r th1s")
// false

It does not look like a nice solution, but it does the job. I am interested in a more elegant solution though.

PS: don't forget to add the letter 'i' for case insensivity!

\$\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.