简体   繁体   English

筛选不包含其他数组中的字符串的字符串?

[英]Filter strings which doesn't includes strings from other array?

I want to filter an array of urls by excluding ones that contain any substrings that are in a blacklist array. 我想通过排除包含黑名单数组中任何子字符串的URL来过滤URL数组。

const urls = [
'http://example.com/people/chuck', 
'http://example.com/goats/sam', 
'http://example.com/goats/billy', 
'http://example.com/goats/linda', 
'http://example.com/cows/mary', 
'http://example.com/cows/betty', 
'http://example.com/people/betty']

const blacklist = ['cows', 'goats']

let cleanUrls = [];

I can do this with for-loops but I want to find a clean/concise way using filter and/or reduce. 我可以使用for循环来做到这一点,但是我想使用filter和/或reduce来找到一种简洁的方法。

If I didn't need to loop over x number of blacklist items: 如果我不需要遍历x个黑名单项目:

cleanUrls = urls.filter( url => !url.includes(blacklist[0]) )                  
                .filter( url => !url.includes(blacklist[1]) ) 

I also don't want to just iterate through the blacklist with a forEach or map because I want to immediately stop if a particular url matches any blacklist entry. 我也不想只使用forEach或map遍历黑名单,因为如果特定的网址与任何黑名单条目匹配,我想立即停止。

Plain JS please. 请使用普通的JS。 Thank you. 谢谢。 :) :)

You can use filter() like this: 您可以像这样使用filter()

const cleanUrls = urls.filter(u => blacklist.every(s => !u.includes(s)));

Or 要么

const cleanUrls = urls.filter(u => !blacklist.some(s => u.includes(s)));

Description: 描述:

  • .includes() will check the existence of a sub-string withing another string. .includes()将检查子字符串是否与另一个字符串一起存在。
  • .every() will check whether none of the strings of blacklist array exists in a particular URL. .every()将检查特定URL中是否不存在blacklist数组的字符串。
  • .some() will check whether any of the string of blacklist array exists in a particular URL. .some()将检查特定URL中是否存在blacklist数组的任何字符串。
  • .filter() will select only those URL's which will pass the test. .filter()将仅选择将通过测试的那些URL。

Demo: 演示:

 const urls = [ 'http://example.com/people/chuck', 'http://example.com/goats/sam', 'http://example.com/goats/billy', 'http://example.com/goats/linda', 'http://example.com/cows/mary', 'http://example.com/cows/betty', 'http://example.com/people/betty' ]; const blacklist = ['cows', 'goats']; const cleanUrls = urls.filter(u => blacklist.every(s => !u.includes(s))); console.log(cleanUrls); 

Docs: 文件:

You can do this with filter() , some() and includes() methods. 您可以使用filter()some()includes()方法来实现。

 const urls = ['http://example.com/people/chuck', 'http://example.com/goats/sam', 'http://example.com/goats/billy', 'http://example.com/goats/linda', 'http://example.com/cows/mary', 'http://example.com/cows/betty', 'http://example.com/people/betty']; const blacklist = ['cows', 'goats'] const result = urls.filter(url => !blacklist.some(e => url.includes(e))) console.log(result) 

It might be easuer to turn the blacklist i to a Regex: 将黑名单i转换为正则表达式可能会比较容易:

 const block = new RegExp(blacklist.join("|"));

Them its as simple as: 它们非常简单:

 cleanUrls = urls.filter(url => !url.match(block));

You can use forEach & indexOf to check if the element from second array is present in the url 您可以使用forEach&indexOf检查url中是否存在第二个数组中的元素

 const urls = [ 'http://example.com/people/chuck', 'http://example.com/goats/sam', 'http://example.com/goats/billy', 'http://example.com/goats/linda', 'http://example.com/cows/mary', 'http://example.com/cows/betty', 'http://example.com/people/betty' ] const blacklist = ['cows', 'goats']; var newArray = []; blacklist.forEach(function(item) { if (newArray.length === 0) { newArray = urls.filter(function(items) { return (items.indexOf(item) === -1) }) } else { newArray = newArray.filter(function(items) { return (items.indexOf(item) === -1) }) } }); console.log(newArray) 

I also don't want to just iterate through the blacklist with a forEach or map because I want to immediately stop if a particular url matches any blacklist entry. 我也不想只使用forEach或map遍历黑名单,因为如果特定的网址与任何黑名单条目匹配,我想立即停止。

The function stop searching if an element from the blacklist appears. 该功能停止搜索是否出现黑名单中的元素。

Recursive way to solve this problem: 解决此问题的递归方法:

 const urls = [ 'http://example.com/people/chuck', 'http://example.com/goats/sam', 'http://example.com/goats/billy', 'http://example.com/goats/linda', 'http://example.com/cows/mary', 'http://example.com/cows/betty', 'http://example.com/people/betty'] const blacklist = ['cows', 'goats'] function filter([url, ...urls] =[], blackList=[], filteredUrls =[] ){ return !url || blacklist.some(el => url.includes(el)) ? filteredUrls : filter(urls, blackList, [...filteredUrls, url]) } console.log(filter(urls, blacklist)); 

Others have answered the question. 其他人已经回答了这个问题。 Providing two different scenarios. 提供两种不同的方案。

 const urls = [ 'http://example.com/people/chuck', 'http://example.com/goats/billy', 'http://example.com/aagoatsss/billyyy', 'http://example.com/people/betty' ] const blacklist = ['cows', 'goats'] //1st approach. It will also block 'http://example.com/aagoatsss/billyyy' let cleanUrls1 = urls.filter( url => blacklist.find( blockWord => url.indexOf(blockWord) != -1 //Url contains Block Word ) === undefined //url donot contain any block word. ) console.log(cleanUrls1) //2nd approach. It will pass 'http://example.com/aagoatsss/billyyy' let cleanUrls2 = urls.filter( url => blacklist.find( blockWord => url.split('/').indexOf(blockWord) != -1 //Url contains Block Word ) === undefined //url donot contain any block word. ) console.log(cleanUrls2) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM