将字符串数组传递给 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
);