2
votes

Comment puis-je échanger les valeurs de deux caractères différents dans une chaîne avec PHP? A devient B, B devient A

J'ai une chaîne en PHP. Je veux échanger un certain caractère avec la valeur d'un autre caractère. Si je le fais à ma manière, A devenant B remplacera A par B mais les valeurs B déjà existantes resteront les mêmes. Lorsque j'essaye de permuter B en A, il y a bien sûr des valeurs qui n'ont pas été échangées à l'origine, car elles étaient déjà là.

J'ai essayé ce code.

$hex = "long_hex_string_not_included_here";
$hex = str_replace($a,$b,$hex);
//using this later will produced unwanted extra swaps
$hex = str_replace($b,$a,$hex);

Je recherche une fonction pour permuter ces valeurs.


0 commentaires

5 Réponses :


1
votes

Utilisez une valeur Temp (qui n'apparaît pas dans votre chaîne. Cela peut être n'importe quoi):

$temp = "_";
$a = "a";
$b = "b";
$hex = "abcdabcd";
$hex = str_replace($a,    $temp, $hex); // "_bcd_bcd"
$hex = str_replace($b,    $a,    $hex); // "_acd_acd"
$hex = str_replace($temp, $a,    $hex); // "bacdbacd"

// Or, alternativly a bit shorter:
$temp = "_";
$a = "a";
$b = "b";
$hex = str_replace([$a, $b, $temp], [$temp, $a, $b] $hex);


1 commentaires

Mais bien sûr, vous devrez vous assurer que la valeur C n'existe pas déjà dans la chaîne ou vous obtiendrez un autre résultat indésirable



2
votes

Nous pourrions simplement essayer de remplacer une troisième valeur intermédiaire par B , puis remplacer tous les A par B , puis remplacez le marqueur par A . Mais cela laisse toujours ouverte la possibilité que le caractère marqueur puisse déjà apparaître quelque part dans la chaîne.

Une approche plus sûre consiste à convertir la chaîne d'entrée en un tableau de caractères, puis à parcourir le tableau en vérifiant simplement chaque index pour A ou B , et permutez en conséquence.

$input = "AzzzzB";
echo $input ."\n";
$arr = str_split($input);

for ($i=0; $i < count($arr); $i++) {
    if ($arr[$i] == 'A') {
        $arr[$i] = 'B';
    }
    else if ($arr[$i] == 'B') {
        $arr[$i] = 'A';
    }
}
$output = implode('', $arr);
echo $ouput;

AzzzzB
BzzzzA

Notez également que cette approche est efficace et ne nécessite que de parcourir l'entrée chaîne une fois.


1 commentaires

Bien que cela n'ait pas le problème de la valeur intermédiaire existant dans la chaîne, cela ne fonctionnera pas pour les longueurs de caractères> 1. Et je suis curieux de savoir comment cela fonctionne. Mon intermédiaire a un remplacement supplémentaire, mais c'est aussi une manipulation de chaîne. J'aime cette réponse, +1.



9
votes

Utilisez simplement strtr . C'est ce pour quoi il a été conçu:

bacacb

Résultat:

$string = "abcbca";
echo strtr($string, array('a' => 'b', 'b' => 'a'));

La fonctionnalité clé qui aide ici est que lorsque strtr code> est appelé sous la forme à deux arguments:

Une fois qu'une sous-chaîne a été remplacée, sa nouvelle valeur ne sera plus recherchée.

C'est ce qui empêche le a qui a été remplacé par b d'être à nouveau remplacé par a .

Démo sur 3v4l.org


1 commentaires

J'ai cloué la question d'entretien, vous avez donné la meilleure réponse +1.



0
votes

Une autre façon pourrait être de str_split la chaîne et d'utiliser array_map par caractère. Si a , renvoyez b et vice versa. Sinon, renvoie la valeur d'origine.

baab test abba

Résultat

$hex = "abba test baab";
$hex = array_map(function ($x) {
    return ($x === 'a') ? 'b' : (($x === 'b') ? 'a' : $x);
}, str_split($hex));

echo implode('', $hex);

Démo


0 commentaires

0
votes

Ma solution fonctionne pour une sous-chaîne. Le code n'est pas clair mais je veux vous montrer une façon de penser.

$html = "dasdfdasdff";
$firstLetter = "d";
$secondLetter = "a";
$firstLetterPositions = array();
$secondLetterPositions = array();

$lastPos = 0;
while (($lastPos = strpos($html, $firstLetter, $lastPos))!== false) {
    $firstLetterPositions[] = $lastPos;
    $lastPos = $lastPos + strlen($firstLetter);
}

$lastPos = 0;
while (($lastPos = strpos($html, $secondLetter, $lastPos))!== false) {
    $secondLetterPositions[] = $lastPos;
    $lastPos = $lastPos + strlen($secondLetter);
}

for ($i = 0; $i < count($firstLetterPositions); $i++) {
    $html = substr_replace($html, $secondLetter, $firstLetterPositions[$i], count($firstLetterPositions[$i]));
}

for ($i = 0; $i < count($secondLetterPositions); $i++) {
    $html = substr_replace($html, $firstLetter, $secondLetterPositions[$i], count($secondLetterPositions[$i]));
}
var_dump($html);


1 commentaires

Cela n'échoue-t-il pas lorsque vous remplacez une chaîne par une autre valeur de longueur? Par exemple. 'a' avec 'bb'? Cette solution est assez exagérée par rapport aux remplacements de 3 chaînes et n'offre pas beaucoup de valeur.