Wann wird strtr vs str_replace verwendet?

85

Es fällt mir schwer zu verstehen, wann strtres vorzuziehen wäre str_replaceoder umgekehrt. Es scheint möglich zu sein, mit beiden Funktionen genau die gleichen Ergebnisse zu erzielen, obwohl die Reihenfolge, in der Teilzeichenfolgen ersetzt werden, umgekehrt ist. Beispielsweise:

echo strtr('test string', 'st', 'XY')."\n";
echo strtr('test string', array( 's' => 'X', 't' => 'Y', 'st' => 'Z' ))."\n";
echo str_replace(array('s', 't', 'st'), array('X', 'Y', 'Z'), 'test string')."\n";
echo str_replace(array('st', 't', 's'), array('Z', 'Y', 'X'), 'test string');

Dies gibt aus

YeXY XYring
YeZ Zring
YeXY XYring
YeZ Zring

Gibt es neben der Syntax einen Vorteil bei der Verwendung übereinander? Gibt es Fälle, in denen man nicht ausreichen würde, um ein gewünschtes Ergebnis zu erzielen?

andrewtweber
quelle
3
Unter dem Gesichtspunkt der Lesbarkeit kann strtrdies leicht falsch verstanden werden, da strstrdies ganz anders ist. Ich fange an zu glauben, ich sei Legastheniker. Ich werde diesen Fehler nicht mit str_replace machen.
Programster

Antworten:

134

Erster Unterschied:

Ein interessantes Beispiel für ein anderes Verhalten zwischen strtrund finden Sie str_replaceim Kommentarbereich des PHP-Handbuchs:

<?php
$arrFrom = array("1","2","3","B");
$arrTo = array("A","B","C","D");
$word = "ZBB2";
echo str_replace($arrFrom, $arrTo, $word);
?>
  • Ich würde als Ergebnis erwarten: "ZDDB"
  • Diese Rückgabe lautet jedoch: "ZDDD" (weil B = D gemäß unserem Array)

Verwenden Sie stattdessen "strtr", damit dies funktioniert:

<?php
$arr = array("1" => "A","2" => "B","3" => "C","B" => "D");
$word = "ZBB2";
echo strtr($word,$arr);
?>
  • Dies gibt zurück: "ZDDB"

Dies bedeutet, dass dies str_replaceein globalerer Ansatz für das Ersetzen ist, während strtrdie Zeichen einfach einzeln übersetzt werden.


Ein weiterer Unterschied:

Angesichts des folgenden Codes (entnommen aus dem PHP String Replacement Speed ​​Comparison ):

<?php
$text = "PHP: Hypertext Preprocessor";

$text_strtr = strtr($text
    , array("PHP" => "PHP: Hypertext Preprocessor"
        , "PHP: Hypertext Preprocessor" => "PHP"));
$text_str_replace = str_replace(array("PHP", "PHP: Hypertext Preprocessor")
    , array("PHP: Hypertext Preprocessor", "PHP")
    , $text);
var_dump($text_strtr);
var_dump($text_str_replace);
?>

Die resultierenden Textzeilen sind:

Zeichenfolge (3) "PHP"
Zeichenfolge (27) "PHP: Hypertext Preprocessor"


Die Haupterklärung:

Dies geschieht, weil:

  • strtr : sortiert seine Parameter nach Länge in absteigender Reihenfolge, also:

    1. es wird dem größten "mehr Bedeutung" geben, und dann wird es übersetzt, da der Betreff selbst der größte Schlüssel des Ersatzarrays ist.
    2. Da alle Zeichen des Betreffs ersetzt wurden, endet der Vorgang dort.
  • str_replace : Es funktioniert in der Reihenfolge, in der die Schlüssel definiert sind.

    1. es findet den Schlüssel "PHP" im Betreff und ersetzt ihn durch: "PHP: Hypertext Preprocessor", was als Ergebnis ergibt:

      "PHP: Hypertext-Präprozessor: Hypertext-Präprozessor".

    2. dann findet es den nächsten Schlüssel: "PHP: Hypertext Preprocessor" im resultierenden Text des vorherigen Schritts, so dass es durch "PHP" ersetzt wird, was als Ergebnis ergibt:

      "PHP: Hypertext Preprocessor".

    3. Es sind keine Schlüssel mehr zu suchen, daher endet der Austausch dort.

Nicolás Ozimica
quelle
2
Ah ok danke! Ich wusste nicht, dass strtr nach Länge übersetzt - ich dachte, es wäre in umgekehrter Reihenfolge.
Andrewwweber
Wie in php.net dokumentiert, verfügt die Funktion str_replace über einen weiteren Parameter mit dem Namen "count", der angibt, wie oft der Austausch durchgeführt werden soll. Aber ich kann diesen Parameter trotzdem nicht verwenden. Weiß jemand warum?
Vantrung-Cuncon
1
@ vantrung-cuncon Dafür ist dieser Parameter nicht gedacht. In den Dokumenten heißt es: "Dies wird auf die Anzahl der durchgeführten Ersetzungen eingestellt." Sie müssen eine andere Lösung finden, wenn Sie str_replace auf eine bestimmte Anzahl von Ersetzungen beschränken möchten.
Jdhartley
1
Die Begrenzung der Anzahl der Ersetzungen kann nützlich sein, wenn Sie das erste Auftreten eines Akronyms in die erweiterte Version ersetzen möchten, dh das erste Auftreten von "WHO" in "WHO (Weltgesundheitsorganisation)" ändern möchten.
Michał Tatarynowicz
strtrErsetzt keinen Text, der durch vorherige Ersetzungen eingefügt wurde. strtr('foo', array('oo' => 'ie', 'e' => 't'))kehrt 'fie'statt 'fit'wie str_replacefolgt zurück. Somit wird das von @Pies angesprochene Problem automatisch behoben.
David Harkness
21

Es scheint möglich zu sein, mit beiden Funktionen genau die gleichen Ergebnisse zu erzielen

Dies ist nicht immer der Fall und hängt von den von Ihnen angegebenen Such- und Ersetzungsdaten ab. Wenn sich die beiden Funktionen unterscheiden, siehe: Hat PHP str_replace eine Beschränkung von mehr als 13 Zeichen?

  • strtrwird nicht in Teilen der Zeichenfolge ersetzt, die bereits ersetzt wurden - str_replaceersetzt innerhalb von Ersetzungen.
  • strtrbeginnt mit der längsten Taste zuerst, falls Sie sie mit zwei Parametern aufrufen - str_replacewird von links nach rechts ersetzt.
  • str_replacekann die Anzahl der durchgeführten Ersetzungen zurückgeben - strtrbietet keinen solchen Zählwert.
hakre
quelle
7

Ich denke, strtrbietet eine flexiblere und bedingte Ersetzung, wenn sie mit zwei Argumenten verwendet wird, zum Beispiel: Wenn die Zeichenfolge 1 ist, ersetzen Sie sie durch a, aber wenn die Zeichenfolge 10 ist, ersetzen Sie sie durch b. Dieser Trick konnte nur erreicht werden durch strtr.

$string = "1.10.0001";  
echo strtr($string, array("1" => "a", "10" => "b"));  
// a.b.000a  

siehe: Php Manual Strtr .

Arif RH
quelle
2

Hinweis im Handbuch STRTR-- Beschreibung string strtr (string $ str, string $ from, string $ to) string strtr (string $ str, array $ replace_pairs) Wenn drei Argumente angegeben werden, gibt diese Funktion eine Kopie von str zurück, wobei ...

STR_REPLACE-- ... Wenn Suchen oder Ersetzen Arrays sind, werden ihre Elemente zuerst bis zuletzt verarbeitet . ...

STRTR wirkt sich in jeder Runde NICHT auf die nächste aus, ABER STR_REPLACE.

Null Keine
quelle