J'essaie de comprendre comment supprimer un caractère sur deux (à partir du premier) d'une chaîne en Javascript. Par exemple, la chaîne "Ceci est un test!" devrait devenir "hsi etTi sats!" Je souhaite également enregistrer chaque caractère supprimé dans un autre tableau.
J'ai essayé d'utiliser la méthode de remplacement et la méthode d'épissage, mais je n'ai pas réussi à les faire fonctionner correctement. Principalement parce que replace ne remplace que le premier caractère.
function encrypt(text, n) { if (text === "NULL") return n; if (n <= 0) return text; var encArr = []; var newString = text.split(""); var j = 0; for (var i = 0; i < text.length; i += 2) { encArr[j++] = text[i]; newString.splice(i, 1); // this line doesn't work properly } }
9 Réponses :
function encrypt(text) { text = text.split(""); var removed = [] var encrypted = text.filter((letter, index) => { if(index % 2 == 0){ removed.push(letter) return false; } return true }).join("") return { full: encrypted + removed.join(""), encrypted: encrypted, removed: removed } } console.log(encrypt("This is a test!"))
Splice ne fonctionne pas, car si vous supprimez un élément d'un tableau dans for loop
, les index seront probablement erronés lors de la suppression d'un autre élément.
Ouais, je le sais. C'est pourquoi j'essaie de trouver une meilleure solution, car je suis à court d'idées.
Qu'en est-il de l'utilisation de la méthode de filtrage? De cette façon, il est facile d'enregistrer les éléments supprimés dans un tableau.
Il serait probablement plus facile d'utiliser une expression régulière et .replace
: capturez deux caractères dans des groupes de capture séparés, ajoutez le premier caractère à une chaîne et remplacez-le par le second. Ensuite, vous aurez la première moitié de la sortie dont vous avez besoin dans une chaîne, et la seconde dans une autre: il suffit de les concaténer et de renvoyer:
function encrypt(text) { let removedText = ''; const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => { // in case the match was at the end of the string, // and the string has an odd number of characters: if (!secondChar) secondChar = ''; // remove the firstChar from the string, while adding it to removedText: removedText += firstChar; return secondChar; }); return replacedText1 + removedText; } console.log(encrypt('This is a test!'));
"!" est manquant. En général, cela ne fonctionnera pas pour les chaînes de longueur impaire.
Merci, j'ai oublié la ponctuation, rendez le deuxième groupe de capture facultatif
Assez simple avec .reduce ()
pour créer les deux tableaux que vous semblez vouloir.
function encrypt(text) { return text.split("") .reduce(({odd, even}, c, i) => i % 2 ? {odd: [...odd, c], even} : {odd, even: [...even, c]} , {odd: [], even: []}) } console.log(encrypt("This is a test!"));
Ils peuvent être convertis en chaînes en utilisant .join ("")
si vous le souhaitez.
Je pense que vous étiez sur la bonne voie. Ce que vous avez manqué est de remplacer en utilisant une chaîne ou RegExp.
La méthode replace () renvoie une nouvelle chaîne avec certaines ou toutes les correspondances d'un modèle remplacées par un remplacement. Le modèle peut être une chaîne ou un RegExp, et le remplacement peut être une chaîne ou une fonction à appeler pour chaque correspondance. Si pattern est une chaîne, seule la première occurrence sera remplacée.
Source: Chaîne .prototype.replace ()
Si vous remplacez une valeur (et non une expression régulière), seule la première instance de la valeur sera remplacée. Pour remplacer toutes les occurrences d'une valeur spécifiée, utilisez le modificateur global (g)
Source: Méthode JavaScript String replace () p >
Donc, ma suggestion serait de continuer avec replace et de passer le bon RegExp à la fonction, je suppose que vous pouvez le comprendre à partir de cet exemple - cela supprime chaque seconde occurrence pour le char 't':
let count = 0; let testString = 'test test test test'; console.log('original', testString); // global modifier in RegExp let result = testString.replace(/t/g, function (match) { count++; return (count % 2 === 0) ? '' : match; }); console.log('removed', result);
Vous pourriez réduire
les caractères de la chaîne et les regrouper dans des tableaux séparés à l'aide de l'opérateur %
. Utilisez destructuring pour obtenir le tableau 2D renvoyé pour séparer les variables
let str = "This is a test!", odd = [], even = []; for (var i = 0; i < str.length; i++) { i % 2 === 0 ? even.push(str[i]) : odd.push(str[i]) } console.log(odd.join('')) console.log(even.join(''))
Utilisation d'une boucle for
:
let str = "This is a test!"; const [even, odd] = [...str].reduce((r,char,i) => (r[i%2].push(char), r), [[],[]]) console.log(odd.join('')) console.log(even.join(''))
comme ça?
var text = "This is a test!" var result = "" var rest = "" for(var i = 0; i < text.length; i++){ if( (i%2) != 0 ){ result += text[i] } else{ rest += text[i] } } console.log(result+rest)
Peut-être avec fractionnement, filtrage et jointure:
const remaining = myString.split('').filter((char, i) => i % 2 !== 0).join(''); const deleted = myString.split('').filter((char, i) => i % 2 === 0).join('');
Excellent. J'utilise celui-ci.
Vous pouvez prendre un tableau et une épissure et pousser chaque deuxième élément à la fin du tableau.
function encrypt(string) { var array = [...string], i = 0, l = array.length >> 1; while (i <= l) array.push(array.splice(i++, 1)[0]); return array.join(''); } console.log(encrypt("This is a test!"));
Je ne sais pas à quel point vous vous souciez des performances, mais l'utilisation de regex n'est pas très efficace. Un test simple pour une chaîne assez longue montre que l'utilisation de la fonction de filtre est en moyenne environ 3 fois plus rapide, ce qui peut faire toute la différence lorsqu'elle est effectuée sur de très longues chaînes ou sur de très nombreuses chaînes courtes.
function test(func, n){ var text = ""; for(var i = 0; i < n; ++i){ text += "a"; } var start = new Date().getTime(); func(text); var end = new Date().getTime(); var time = (end-start) / 1000.0; console.log(func.name, " took ", time, " seconds") return time; } function encryptREGEX(text) { let removedText = ''; const replacedText1 = text.replace(/(.)(.)?/g, (_, firstChar, secondChar) => { // in case the match was at the end of the string, // and the string has an odd number of characters: if (!secondChar) secondChar = ''; // remove the firstChar from the string, while adding it to removedText: removedText += firstChar; return secondChar; }); return replacedText1 + removedText; } function encrypt(text) { text = text.split(""); var removed = ""; var encrypted = text.filter((letter, index) => { if(index % 2 == 0){ removed += letter; return false; } return true }).join("") return encrypted + removed } var timeREGEX = test(encryptREGEX, 10000000); var timeFilter = test(encrypt, 10000000); console.log("Using filter is faster ", timeREGEX/timeFilter, " times")
Utiliser en fait un tableau pour stocker les lettres supprimées, puis les joindre est beaucoup plus efficace que en utilisant une chaîne et en y concaténant des lettres.
J'ai changé un tableau en chaîne dans la solution de filtre pour le rendre identique à celui de la solution regex, afin qu'ils soient plus comparables.
Quel est le paramètre n dans cette fonction?
Si vous la bouclez à l'envers, cela fonctionnera:
for (var i = text.length - 1; i> = 0; i - = 2)
. Les indices seront corrects.