2
votes

Comment obtenir des caractères de position pairs et impairs à partir d'une chaîne?

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


2 commentaires

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.


9 Réponses :


1
votes

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.


2 commentaires

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.



3
votes

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!'));


2 commentaires

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



1
votes

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.


0 commentaires

1
votes

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


0 commentaires

3
votes

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(''))


0 commentaires

1
votes

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)


0 commentaires

1
votes

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('');


1 commentaires

Excellent. J'utilise celui-ci.



2
votes

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!"));


0 commentaires

1
votes

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

 filter vs regex - performance test result

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.


0 commentaires