¿Pasar una matriz de cadenas en JavaScript indexOf ()? Ejemplo: str.indexOf (arrayOfStrings)?

0

Necesito poder verificar una URL para ver si contiene un dominio de segundo nivel (SLD) para un servicio de transmisión válido. Tenga en cuenta que "hulu" en www.hulu.com es lo que quiero decir con SLD.

En lugar de analizar la URL con expresiones regulares para obtener solo el SLD, o usar algo como location.hostname.split('.').pop()para obtener el SLD, pensé que podría usar indexOf en su lugar. Y esto funciona muy bien (al menos para mí, me doy cuenta de que tiene al menos una limitación seria, vea mi nota a continuación).

Ejemplo. Digamos que quiero ver si https://www.hulu.com/watch/...es un enlace de Hulu. Esto funciona:

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

Lo que quiero poder hacer es pasar una matriz de posibles cadenas a indexOf. Algo como esto:

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)

Pero, por supuesto, esto no funciona porque indexOf()se espera que se le pase una cadena, no una matriz de cadenas.

Entonces, ¿hay alguna solución similarmente fácil y elegante (vainilla JS) en la que no estoy pensando?

La siguiente cosa más fácil que podría pensar sería recorrer mi matriz de validSLD y llamar a indexOf en cada uno de los SLD. Y quizás ese sea el mejor enfoque. Solo pensé en ver si alguien más tenía una mejor solución. ¡Gracias por adelantado!

NOTA: Me doy cuenta de que todo mi enfoque es un enfoque perezoso y podría dar lugar a posibles problemas. Por ejemplo, https://www.amazon.com/how-cancel-hulu-subscription-membership/...también devolvería verdadero usando el código anterior, porque la palabra "hulu" existe en la cadena ... pero no es una SLD. Estoy de acuerdo con eso porque tenemos cierto control sobre las URL que necesitamos validar.

5
  • 1
    ¿El uso de la API de URL es lo suficientemente sencillo ?
    PM 77-1
    22 feb a las 19:56
  • 2
    Debe hacerlo al revés forEacho incluso mejor para everyo tal vez solo para el someelemento de cadena de / en su matriz validSLDs, debe verificar si es parte de la cadena que se va a validar. 22 feb a las 20:02
  • Es de esperar que también sepa que este enfoque no es a prueba de balas, por ejemplo, hulupor cualquier motivo, podría ser parte del nombre de ruta de un dominio totalmente diferente. 22 feb a las 20:08
  • @ PM77-1, la API de URL no me dará el dominio de segundo nivel, ¿correcto? Ya tenemos una lista de SLD válidos (hoopla, kanopy, etc.) pero no están en el formato www.hoopla.com. Son literalmente SLD sin www ni .com. Así que estaba tratando de evitar la necesidad de eliminar eso antes de comparar. ¿Pero tal vez me falta algo en la API de URL? 22 feb a las 21:59
  • @PeterSeliger sí, definitivamente pensé en el hecho de que este enfoque no es a prueba de balas. Pero la verdad es que estoy tratando con algunas URL atípicas muy raras. El 99,9% de las URL que tratamos en el trabajo son correctas. Hasta ahora, solo se ha descubierto una única URL (de los cientos de miles con los que tratamos) que se vincula a IMDB en lugar de a un servicio de transmisión válido. Y no, no es porque sea un enlace IMDB-TV. Lo comprobé. Podría haber incluido fácilmente IMDB en la lista negra, pero en cambio pensé que sería más seguro incluir en la lista blanca nuestros SLD válidos conocidos. 22 feb a las 22:04
1

Simplemente haga una pequeña función auxiliar que haga lo que dijo, recorra la matriz y verifique cada valor. Una forma eficiente de hacerlo es con Array.some , ya que devolverá verdadero tan pronto como encuentre una coincidencia verdadera.

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));
4
  • 1
    ... ¿por qué no hacer uso de en String.prototype.includeslugar de indexOf? 22 feb a las 20:11
  • @PeterSeliger Seguro, podrías hacerlo. Sé que OP está familiarizado con indexOf.
    James
    22 feb a las 20:13
  • 1
    @PeterSeliger, ¡ese es un punto excelente! En realidad, no necesito el índice en absoluto. incluye () es un enfoque mucho mejor en esta situación. Ha sido un largo día. Debería haber pensado en eso. ¡Gracias! 22 feb a las 22:17
  • @James, aprecio que te quedes con indexOf () para tu respuesta. Resulta que estoy familiarizado con las inclusiones, pero si no lo hubiera estado, habría tenido dos funciones para investigar. Tal como está, solo tengo que repasar la matriz. 22 feb a las 22:24
0
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))

allSLDsareValides un booleano, evalúa truesi todas las cadenas son válidas y falso si hay al menos una cadena no válida.

Si, en cambio, desea realizar un seguimiento de qué SLD son válidos y cuáles no, intente usar un objeto:

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

Luego, cuando necesite acceder a la validez de la SLD, puede verificar la existencia de la clave en validatedStrings:

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

Realmente aprecio todas las sugerencias. Al final, fui con una combinación de sugerencias e hice lo siguiente.

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;
};

Lo que parece funcionar bien (aunque no es a prueba de balas, como se menciona en mi NOTA original y en un comentario). Pasar el enlace IMDB a la función devolvió falso, mientras que pasar un enlace alboroto o kanopy devolvió verdadero. Podría intentar refactorizar un poco más ... pero esto debería funcionar para mis propósitos.

Luego, Peter Seliger escribió una versión aún más sucinta (a continuación) que funciona aún mejor. ¡Especialmente si no te confunden las funciones de flecha anidadas! Haga clic en el botón "Ejecutar fragmento de código" a continuación para ver la respuesta mejorada de Peter en acción.

¡Gracias de nuevo por la ayuda a todos!

Editado por Peter Seliger para aclarar algunos comportamientos del código

P: OP en comentario ...

"... 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. ..."

A:

Si copio y pego, por ejemplo, en la consola del navegador, y lo invoco validateLink('https://www.hulu.com/watch/...'), devuelve falso ... la invocación validateLink('https://www.hoopla.com/watch/...')devuelve verdadero.

E incluso si ['hoopla', 'kanopy', /*...*/]dentro de la función hubiera una matriz dispersa (matriz con emptyranuras, que no lo es), la iteración funcionaría, porque cada método de matriz omite las emptyranuras.

fragmento de código ejecutable para corregir lo dicho anteriormente ...

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
);
5
  • 1
    const validateLink = link => ['hoopla', 'kanopy', /*...*/].some(sdl => link.includes(sdl));hace exactamente lo mismo que el enfoque anterior, solo que mucho más corto y también más expresivo. somedebajo del capó se implementa de manera similar a lo que se le ocurrió. Ambos somey everydevuelven un valor booleano, y ambos salen / rompen inmediatamente sus bucles internos tan pronto como se cumplió la condición ( some) o se violó ( every). 22 feb a las 23:15
  • @PeterSeliger ¡Aprecio que hayas vuelto a esta pregunta varias veces para ayudar! Quería intentar reescribir su función sin usar funciones de flecha anidadas para poder entender más fácilmente lo que está sucediendo. Pero encontré algunos problemas. Entonces intenté copiar / pegar su solución en codepen y obtengo un archivo TypeError: cannot read property 'includes' of undefined. Pero linkse define unas pocas líneas arriba en mi código. ¿Hay algo más que me esté perdiendo? 24 feb a las 22:35
  • Si hago una copia y pego en, por ejemplo, la consola del navegador en este momento, e invoco validateLink('https://www.hulu.com/watch/...')devoluciones false... invocando validateLink('https://www.hoopla.com/watch/...')devoluciones true. E incluso si ['hoopla', 'kanopy', /*...*/]dentro de la función hubiera una matriz dispersa (matriz con emptyranuras, que no lo es), la iteración funcionaría, porque cada método de matriz omite las emptyranuras. Por lo tanto, ni siquiera puedo adivinar qué salió mal en su codepen. 25 de feb a las 8:29
  • ¡Ah! Fue la función de flecha anidada lo que me confundió. Estaba tratando de ejecutar validateLink () sin pasar el enlace como parámetro, lo cual obviamente es incorrecto. Esto funciona perfectamente. ¡Gracias @PeterSeliger! 25 feb a las 15:29
  • Considere usar en su for (let i of validSLDs)lugar. Consulte stackoverflow.com/questions/500504/… para obtener más información. 25 feb a las 15:44
-1

podría intentar usar la filterfunción de matrices:

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)