Dileet
Dileet

Reputation: 2064

ES6 filter an array with Regex

I'm trying to filter an array that contains a bunch of urls. I need to return the urls that only contain the word "contact".

For example there is a link https://www.example.com/v1/contact-us/ca

This should be returned from the filter.

I tried this:

    const regex = new RegExp("/\bcontact\b", 'g' )
    sites.links.filter((val) => {

     console.log(regex.test(val.href))

    })

It currently just sends back false through all the domains, when I know there is one domain that contains the word "contact".

Upvotes: 32

Views: 99357

Answers (7)

unsynchronized
unsynchronized

Reputation: 4938

this is a late reply, but for simplicity, bind is your friend.

let re = /dog/g;
let fn = re.exec.bind(re);
let strings = ['things','a dog is here','fruity ideas'];

let filtered = strings.filter(fn);

console.log({
  strings,
  filtered
})

how it works: filter returns all elements that the callback returns a "truthy" result for. RegExp.exec either returns null or a result set. null is falsey, so any callbacks returning null are filtered out.

Upvotes: 0

Zayaan
Zayaan

Reputation: 417

The best answer I could imagine is:

const sites = {
    links: {
        'http://www.some-site.com/contact-us',
        'http://www.some-site.com/about',
        'http://www.some-site.com/admin'
    }
};
sites.links.forEach(i => {
    console.log(i.search(/\/\bcontact\b/g) > -1);
});

sites.links.forEach() looping through all the links available

i => {/*...*/} ES6 syntax for function(i) {/*...*/}

console.log() logging the result

/\/\bcontact\b/g works the same as new RegExp("/\bcontact\b", "g") i.search(regexp) > -1, "string".search("s") means, it will search the letter "s" in "string" and return its index in the string, if "s" was not "found" in string, then -1 is returned, so we are checking for, is there "s" in "string" and returning the true/false value

The code's ES5 syntax:

sites.links.forEach(function(i) {
    console.log(i.search(/\/\bcontact\b/g) > -1);
});

Upvotes: 0

Marco Santana
Marco Santana

Reputation: 121

My take on this. OP requested regex.

const domains = [{href: 'https://foo'}, {href: 'https:://bar'}, {href: 'https:://bar/contact'}]
  const match = domain => {
    return RegExp('/contact\\b', 'g').test(domain.name)
  }
 const needle = domains.filter(domain.href => match(domain))

RegExp.test returns falsy, therefore you can use it directly as a return in the filter.

Upvotes: 1

felixmosh
felixmosh

Reputation: 35503

You need to return the truthy / falsy result from filter function.

const sites = {
  links: [
    {
      href: 'http://www.some-site.com/contact-us',
    },
    {
      href: 'http://www.some-site.com/about',
    },
    {
      href: 'http://www.some-site.com/admin',
    },
  ],
};

const fitered = sites.links.filter((link) => {
  return link.href.split('/').some((part) => part.includes('contact'));
});

console.log(fitered);

Upvotes: 8

nimondo
nimondo

Reputation: 67

const regex = new RegExp('/contact\\b', 'g');
const matchedSites = sites.links.filter(e => 
  regex.test(e.href));
console.log(matchedSites);

Upvotes: 2

Jaromanda X
Jaromanda X

Reputation: 1

Firstly new RegExp('/\bcontact\b', 'g'); is equivalent to /\/@contact@/g where the @ are backspace character (ASCII 08) ... clearly not what you want

So, you would do new RegExp('/\\bcontact\\b', 'g'); - this is equivalent to /\/\bcontact\b/g

However, the \\b after / is redundant

so ... down to /\/contact\b/g

Using string.match here as regex.test is misused. Below is the description

var sites = { 
    links: [
        {href: 'https://www.example.com/v1/contact-us/ca'},
        {href: 'https://www.example.com/v1/contact-us/au'},
        {href: 'https://www.example.com/v1/contact-us/us'},
        {href: 'https://www.example.com/v1/dontcontact-us/us'}
    ]
};

const regex = new RegExp('/contact\\b', 'g');
const matchedSites = sites.links.filter(({href}) => href.match(regex));
console.log(matchedSites);

The next problem is using the ONE regex multiple times in a regexp.test with g flag. With each call, it will look from the next indexOf previous found substring and with consecutive calls on a same-type string, it basically will return true, false, true, false.

If you want to use regex.test, then don't re-use the same regex unless you know the consequences of doing so or do not use g flag (which here you do not need)

var sites = { 
    links: [
        {href: 'https://www.example.com/v1/contact-us/ca'},
        {href: 'https://www.example.com/v1/contact-us/au'},
        {href: 'https://www.example.com/v1/contact-us/us'},
        {href: 'https://www.example.com/v1/dontcontact-us/us'}
    ]
};

const regex = new RegExp('/contact\\b', 'g');
const correctRegex = new RegExp('/contact\\b');

const matchedSitesFailed = sites.links.filter(({href}) => regex.test(href));
const matchedSitesSuccess = sites.links.filter(({href}) => new RegExp('/contact\\b', 'g').test(href));
const matchedSitesSuccess2 = sites.links.filter(({href}) => correctRegex.test(href));

console.log('failed returns:', matchedSitesFailed.length);
console.log('success returns:', matchedSitesSuccess.length);
console.log('success returns 2:', matchedSitesSuccess2.length);

Upvotes: 57

Aditya Parmar
Aditya Parmar

Reputation: 1179

var links = ["https://www.example.com/v1/contact-us/ca", "https://www.example.com/v1/contact-us/sanjose", "https://www.example.com/v1/meeting-us/ca"];

var newlink = links.filter(function(link){
  return link.includes("contact")
});

console.log(newlink)

Try this. It should work.

Upvotes: 3

Related Questions