1
votes

Comment supprimer un mot dans une chaîne basé sur un tableau en Javascript lorsque la longueur des caractères du mot dans la chaîne est inférieure à celle du tableau?

Je veux supprimer un mot dans une chaîne basé sur un tableau. Mais la longueur des caractères du mot en chaîne est inférieure à celle en tableau. Est-il possible de le faire correspondre à l'aide de regex, puis de le remplacer par une chaîne vide? Sinon, quelles sont les alternatives?

J'ai essayé d'utiliser regex pour faire correspondre le mot, mais je n'y parviens pas. Je ne sais pas comment faire en sorte que l'expression régulière corresponde au minimum à 3 caractères du tableau.

array = ['reading', 'books'];

string = 'If you want to read the book, just read it.';

desiredOutput = 'If you want to  the , just  it.';


// Desired match

'reading' -> match for 'rea', 'read', 'readi', 'readin', 'reading'

'books' -> match for 'boo', 'book', 'books'


0 commentaires

3 Réponses :


1
votes

Une option consiste à faire correspondre 3 caractères de mot ou plus à partir d'une limite de mot, puis d'utiliser une fonction de remplacement pour renvoyer la chaîne vide si l'un des mots commence avec le mot en question:

const array = ['reading', 'books'];
const string = 'If you want to read the book, just read it.';
const output = string.replace(
  /\b\w{3,}/g,
  word => array.some(item => item.startsWith(word)) ? '' : word
);
console.log(output);


0 commentaires

1
votes

La réponse de CertainPerformance est meilleure - plus facile à implémenter et à maintenir, mais il convient de noter que - vous pouvez également générer une expression régulière à partir du tableau.

L'idée est assez simple - si vous voulez correspondre r , re , rea , read , readi , readin , lecture l'expression régulière pour cela est lecture | readin | readi | read | rea | re | r . La raison pour laquelle vous voulez d'abord la plus longue variation est que sinon, le moteur d'expression régulière s'arrêtera à la première correspondance dans les recherches:

/\b(?:reading|readin|readi|read|rea|re|r)\b|\b(?:books|book|boo|bo|b)\b/g

Vous pouvez donc prendre un mot et le décomposer selon ce modèle pour en générer une expression régulière

const array = ['reading', 'books'];
const string = 'The quick brown fox jumps over the lazy dog. If you want to read the book, just read it.';

let pattern = array
  .map(toPattern)
  .join("|");
  
let regex = new RegExp(pattern, "g");
let result = string.replace(regex, "");

console.log(result); 


function allSubstrings(word) {
  let substrings = [];
  for (let i = word.length; i > 0; i--) {
    let sub = word.slice(0, i);
    substrings.push(sub)
  }
  
  return substrings;
}

function toPattern(word) {
  let substrings = allSubstrings(word);
  let pattern = "\\b(?:" + substrings.join("|") + ")\\b";
  
  return pattern;
}

Avec cela, vous pouvez simplement générer l'expression régulière dont vous avez besoin.

function toPattern(word) {
  let substrings = allSubstrings(word);
  //escape backslashes, because this is a string literal and we need \b as content
  let pattern = "\\b(?:" + substrings.join("|") + ")\\b"; 

  return pattern;
}

La dernière chose à faire est de prendre un tableau et de le convertir en regex. Ce qui nécessite de traiter chaque mot , puis de combiner chaque expression régulière en une seule qui correspond à l'un des mots:

\b(?:reading|readin|readi|read|rea|re|r)\b
   ↑↑
   ||____ non-capturing group

Donc, voici comment vous pouvez générer une expression régulière à partir de ce tableau. Dans ce cas, cela fonctionne, mais ce n'est pas garanti, car il y a un danger que cela corresponde à quelque chose que vous ne voulez pas. Par exemple, r correspondra à n'importe quel caractère, il n'a pas nécessairement besoin d'être dans un mot qui correspond à cela.

\breading\b|\breadin\b|\breadi\b|\bread\b|\brea\b|\bre\b|\br\b
↑↑       ↑↑ ↑↑      ↑↑ ↑↑     ↑↑ ↑↑    ↑↑ ↑↑   ↑↑ ↑↑  ↑↑ ↑↑ ↑↑

C'est à ce moment que cela devient plus compliqué, car vous voulez générer un motif plus compliqué pour chaque mot. Vous voulez généralement faire correspondre mots , vous pouvez donc utiliser le caractère de limite de mot \ b ce qui signifie que le modèle de "lecture" peut maintenant ressembler à ceci:

const array = ['reading'];
const string = 'The quick brown fox jumps over the lazy dog';
//                         ^                 ^    

let pattern = array
  .map(word => allSubstrings(word).join("|"))
  .join("|");

let regex = new RegExp(pattern, "g"); 
let result = string.replace(regex, "");

console.log(result); 

function allSubstrings(word) {
  let substrings = [];
  for (let i = word.length; i > 0; i--) {
    let sub = word.slice(0, i);
    substrings.push(sub)
  }
  
  return substrings;
}

Dans l'intérêt de garder la sortie au moins un peu lisible, elle peut à la place être placée dans un groupe et l'ensemble du groupe doit correspondre à un seul mot:

const array = ['reading', 'books'];
const string = 'If you want to read the book, just read it.';

//generate the pattern
let pattern = array
  .map(toPattern) //first, for each word
  .join("|"); //join patterns for all words
  
//convert the pattern to a regex
let regex = new RegExp(pattern, "g"); 

let result = string.replace(regex, "");

//desiredOutput: 'If you want to  the , just  it.';
console.log(result); 


function allSubstrings(word) {
  let substrings = [];
  for (let i = word.length; i > 0; i--) {
    let sub = word.slice(0, i);
    substrings.push(sub)
  }
  
  return substrings;
}

function toPattern(word) {
  let substrings = allSubstrings(word);
  let pattern = substrings.join("|");
  
  return pattern;
}

Donc, vous devez générer ce modèle

function allSubstrings(word) {
  let substrings = [];
  for (let i = word.length; i > 0; i--) {
    let sub = word.slice(0, i);
    substrings.push(sub)
  }
  
  return substrings;
}

function toPattern(word) {
  let substrings = allSubstrings(word);
  let pattern = substrings.join("|");
  
  return pattern;
}

console.log(toPattern("reading"))

Ce qui nous amène à ceci

function allSubstrings(word) {
  let substrings = [];
  for (let i = word.length; i > 0; i--) {
    let sub = word.slice(0, i);
    substrings.push(sub)
  }
  
  return substrings;
}

console.log(allSubstrings("reading"))

Cela suffira à résoudre votre tâche. Il est donc possible de générer une expression régulière. Le dernier ressemble à ceci:

let regex = /r|re|rea|read/g
//           ↑_________________
console.log(               //  |
  "read".replace(regex, "")//  |
// ↑___________________________|
)

Mais la majeure partie de sa génération est consacrée à essayer de générer quelque chose qui fonctionne . Ce n'est pas forcément une solution complexe mais comme mentionné, celle suggérée par CertainPerformance est meilleure car elle est plus simple, ce qui signifie moins de chance d'échouer et elle serait plus facile à maintenir pour l'avenir.


0 commentaires

0
votes

Je ne connais pas de manière directe de le faire, mais vous pouvez créer votre propre modèle d'expression régulière, comme ceci:

// This function create a regex pattern string for each word in the array.
// The str is the string value (the word), 
// min is the minimum required letters in eac h word 
function getRegexWithMinChars(str, min) {
    var charArr = str.split("");
    var length = charArr.length;
    var regexpStr = "";
    for(var i = 0; i < length; i++){
        regexpStr +="[" + charArr[i] + "]" + (i < min ? "" : "?");
    }
    return regexpStr;
}

// This function returns a regexp object with the patters of the words in the array
function getStrArrayRegExWithMinChars(strArr, min) {
    var length = strArr.length;
    var regexpStr = "";
    for(var i = 0; i < length; i++) {
        regexpStr += "(" + getRegexWithMinChars(strArr[i], min) + ")?";
    }
    return new RegExp(regexpStr, "gm");
}

var regexp = getStrArrayRegExWithMinChars(searchArr, 3);

// With the given regexp I was able to use string replace to 
// find and replace all the words in the string
str.replace(regexp, "");

//The same can be done with one ES6 function
const getStrArrayRegExWithMinChars = (searchArr, min) => {
    return searchArr.reduce((wordsPatt, word) => {
        const patt = word.split("").reduce((wordPatt, letter, index) => {
                return wordPatt + "[" + letter + "]" + (index < min ? "" : "?");
            },"");
        return wordsPatt + "(" + patt + ")?";
    }, "");
}

var regexp = getStrArrayRegExWithMinChars(searchArr, 3);

// With the given regexp I was able to use string replace to 
// find and replace all the words in the string
str.replace(regexp, "");


0 commentaires