将字符串数组传递给 JavaScript indexOf()?示例:str.indexOf(arrayOfStrings)?
Pass an array of strings into JavaScript indexOf()? Example: str.indexOf(arrayOfStrings)?
我需要能够检查 URL 以查看它是否包含有效流媒体服务的二级域 (SLD)。请注意,www.hulu.com 中的“hulu”是我所说的 SLD。
与其使用正则表达式解析 URL 来获取 SLD,或者使用 location.hostname.split('.').pop()
之类的东西来获取 SLD,我想我可以改用 indexOf。这很好用(至少对我来说,我意识到它至少有一个严重的限制 - 请参阅下面的注释)。
例子。假设我想看看 https://www.hulu.com/watch/...
是否是 Hulu link。这有效:
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()
期望传递的是字符串,而不是字符串数组。
那么有没有一些我没有想到的类似简单、优雅(vanilla JS)的解决方案?
我能想到的下一个最简单的事情是遍历我的 validSLD 数组并在每个 SLD 上调用 indexOf。也许这是最好的方法。我只是想看看是否还有其他人有更好的解决方案。提前致谢!
注意:我意识到我的整个方法是一种惰性方法,可能会导致可能出现的问题。例如,使用上面的代码,https://www.amazon.com/how-cancel-hulu-subscription-membership/...
也会 return 为真,因为字符串中存在单词“hulu”……但不是 SLD。我同意这一点,因为我们可以控制我们需要验证的 URL。
你可以尝试使用数组的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)
只需编写一个小辅助函数来执行您所说的操作,遍历数组并检查每个值。一种有效的方法是使用 Array.some,因为一旦找到真实匹配,它就会 return 为真。
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 link 传递给函数返回 false,而传递 hoopla 或 kanopy link 返回 true。我可能会尝试再重构一点......但这应该适合我的目的。
然后 Peter Seliger 写了一个更简洁的版本(如下),效果更好。特别是如果你没有被嵌套的箭头函数搞糊涂的话!单击下面的“运行 代码片段”按钮,查看 Peter 改进后的实际答案。
再次感谢大家的帮助!
由 Peter Seliger 编辑 以澄清一些代码行为
问:OP 评论 ...
"... But I ran into some issues. So then I tried copy/pasting your solution into codepen and I'm getting a TypeError: cannot read property 'includes' of undefined. ..."
答:
如果我复制并粘贴到例如浏览器控制台,并调用 validateLink('https://www.hulu.com/watch/...')
它 returns false ...调用 validateLink('https://www.hoopla.com/watch/...')
returns true.
即使函数内部的 ['hoopla', 'kanopy', /*...*/]
是一个 sparse array(带有 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
);
我需要能够检查 URL 以查看它是否包含有效流媒体服务的二级域 (SLD)。请注意,www.hulu.com 中的“hulu”是我所说的 SLD。
与其使用正则表达式解析 URL 来获取 SLD,或者使用 location.hostname.split('.').pop()
之类的东西来获取 SLD,我想我可以改用 indexOf。这很好用(至少对我来说,我意识到它至少有一个严重的限制 - 请参阅下面的注释)。
例子。假设我想看看 https://www.hulu.com/watch/...
是否是 Hulu link。这有效:
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()
期望传递的是字符串,而不是字符串数组。
那么有没有一些我没有想到的类似简单、优雅(vanilla JS)的解决方案?
我能想到的下一个最简单的事情是遍历我的 validSLD 数组并在每个 SLD 上调用 indexOf。也许这是最好的方法。我只是想看看是否还有其他人有更好的解决方案。提前致谢!
注意:我意识到我的整个方法是一种惰性方法,可能会导致可能出现的问题。例如,使用上面的代码,https://www.amazon.com/how-cancel-hulu-subscription-membership/...
也会 return 为真,因为字符串中存在单词“hulu”……但不是 SLD。我同意这一点,因为我们可以控制我们需要验证的 URL。
你可以尝试使用数组的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)
只需编写一个小辅助函数来执行您所说的操作,遍历数组并检查每个值。一种有效的方法是使用 Array.some,因为一旦找到真实匹配,它就会 return 为真。
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 link 传递给函数返回 false,而传递 hoopla 或 kanopy link 返回 true。我可能会尝试再重构一点......但这应该适合我的目的。
然后 Peter Seliger 写了一个更简洁的版本(如下),效果更好。特别是如果你没有被嵌套的箭头函数搞糊涂的话!单击下面的“运行 代码片段”按钮,查看 Peter 改进后的实际答案。
再次感谢大家的帮助!
由 Peter Seliger 编辑 以澄清一些代码行为
问:OP 评论 ...
"... But I ran into some issues. So then I tried copy/pasting your solution into codepen and I'm getting a TypeError: cannot read property 'includes' of undefined. ..."
答:
如果我复制并粘贴到例如浏览器控制台,并调用 validateLink('https://www.hulu.com/watch/...')
它 returns false ...调用 validateLink('https://www.hoopla.com/watch/...')
returns true.
即使函数内部的 ['hoopla', 'kanopy', /*...*/]
是一个 sparse array(带有 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
);