传递字符串数组到JavaScript indexOf()?例如:str.indexOf (arrayOfStrings)



我需要能够检查URL,看看它是否包含一个有效的流媒体服务的二级域(SLD)。注意,"呼啦"在www.hulu.com中就是我所说的SLD。

而不是用regex解析URL来获得SLD,或者使用像location.hostname.split('.').pop()这样的东西来获得SLD,我想我可以使用indexOf来代替。这种方法非常有效(至少对我来说,我意识到它至少有一个严重的限制——参见下面我的注释)。

的例子。假设我想看看https://www.hulu.com/watch/...是不是Hulu的链接。如此:

let string = 'https://www.hulu.com/watch/...';
string.indexOf('hulu') > -1 ? true : false; // returns true

想要能够做的是传递一个可能的字符串数组到indexOf。像这样:

let validSLDs = ['hulu','netflix']
let string1 = 'www.hulu.com/watch/...';
let string2 = 'http://www.netflix.com/watch/...';
let string3 = 'imdb.com/title/....'
string1.indexOf(validSLDs); // returns true ('hulu' is a valid SLD)
string2.indexOf(validSLDs); // returns true ('netflix' is a valid SLD)
string3.indexOf(validSLDs); // returns false ('imdb' is not a valid SLD)

但是这当然不工作,因为indexOf()期望被传递一个字符串,而不是字符串数组。

所以有一些类似的简单,优雅(香草JS)的解决方案,我没有想到?

我能想到的下一个最简单的事情是循环遍历我的validsld数组并在每个sld上调用indexOf。也许这是最好的方法。我只是想看看有没有人有更好的办法。提前感谢!

注意:我意识到我的整个方法是一种懒惰的方法,可能会导致可能的问题。例如,使用上面的代码,https://www.amazon.com/how-cancel-hulu-subscription-membership/...也会返回true,因为单词"hulu"存在于字符串…但不是特殊障碍。我没有意见,因为我们对需要验证的URL有一些控制。

创建一个小的辅助函数,它执行您所说的操作,循环遍历数组并检查每个值。一个有效的方法是使用Array。有些,因为一旦找到真匹配,它就会返回真。

let validSLDs = ['hulu','netflix']
let string1 = 'www.hulu.com/watch/...';
let string2 = 'http://www.netflix.com/watch/...';
let string3 = 'imdb.com/title/....'
const isURLOK = (testString) => validSLDs.some(v => testString.indexOf(v) > -1);
console.log(isURLOK(string1));
console.log(isURLOK(string2));
console.log(isURLOK(string3));

let string1 = 'www.hulu.com/watch/...';
let string2 = 'http://www.netflix.com/watch/...';
let string3 = 'imdb.com/title/....'
let unverfiedSLDs = [string1, string2, string3]
let validSLDs = ['hulu', 'netflix', 'imdb'];
let allSLDsAreValid = unverifiedSLDs.every(s => controlSLDs.includes(s))

allSLDsareValid是一个布尔值,如果所有字符串都有效,则计算结果为true,如果至少有一个无效字符串,则计算结果为false。

如果您想要跟踪哪些sld是有效的,哪些是无效的,请尝试使用对象:

let validatedStrings = {}
unverifiedSLDs.forEach(s => {
if (validSLDs.includes(s)) {
SLDs[s] = true;
}
})

当您需要访问SLD的有效性时,您可以在validatedStrings中检查键是否存在:

validatedStrings[string1] = true
validatedStrings[string2] = true
validatedStrings[string3] = true
validatedStrings['not-valid'] = undefined

我真的很感谢所有的建议。最后,我综合了一些建议,做了如下的事情:

let link = 'www.imdb.com/title/...';
validateLink = (link) => {
let validSLDs = ['hoopla', 'kanopy' ... ];
for(let i in validSLDs) {
if(link.includes(validSLDs[i])) {
return true;
};
};
return false;
};

这似乎工作得很好(尽管它不是防弹的,正如我在最初的说明和评论中提到的)。将IMDB链接传递给函数返回false,而传递hoopla或kanopy链接返回true。我可能会尝试重构一些……但这应该可以满足我的目的。

然后Peter Seliger写了一个更简洁的版本(下图),效果更好。特别是如果你不被嵌套的箭头函数所迷惑的话!单击"运行代码段"。按钮,查看彼得改进后的答案。

再次感谢大家的帮助!

编辑为了澄清一些代码行为

Q:OP在注释

"…但我遇到了一些问题。所以然后我尝试复制/粘贴你的解决方案到codepen,我得到一个TypeError:无法读取属性'includes'的未定义. ...">

:

如果我做一个复制粘贴到例如浏览器控制台,并调用validateLink('https://www.hulu.com/watch/...')它返回false…调用validateLink('https://www.hoopla.com/watch/...')返回true。

即使函数中的['hoopla', 'kanopy', /*...*/]是一个稀疏数组(具有empty槽位的数组,它不是),迭代也会工作,因为每个数组方法都会跳过empty槽位。

证明上面所说的可执行代码片段…

const validateLink = link =>
['hoopla', 'kanopy', /*...*/].some(sdl => link.includes(sdl));
console.log(
"validateLink('https://www.hulu.com/watch/...') ?",
validateLink('https://www.hulu.com/watch/...') // false
);
console.log(
"validateLink('https://www.hoopla.com/watch/...') ?",
validateLink('https://www.hoopla.com/watch/...') // true
);

您可以尝试使用数组的filter函数:

let validSLDs = ['hulu','netflix']
let string1 = 'www.hulu.com/watch/...';
let string2 = 'http://www.netflix.com/watch/...';
let string3 = 'imdb.com/title/....'
validSLDs.filter(sld => string1.indexOf(sld) !== -1).length > 0; // returns true ('hulu' is a valid SLD)
validSLDs.filter(sld => string2.indexOf(sld) !== -1).length > 0; // returns true ('netflix' is a valid SLD)
validSLDs.filter(sld => string3.indexOf(sld) !== -1).length > 0; // returns false ('imdb' is not a valid SLD)

相关内容

最新更新