2017-08-10 3 views
-3

zu teilen Ich habe eine arithmetische Zeichenfolge, die dem folgenden Muster ähnelt.Regex, um die Zeichenfolge in ein Array von Zahlen und Zeichen unter Verwendung von PHP

a. 1+2+3
b. 2/1*100
c. 1+2+3/3*100
d. (1*2)/(3*4)*100

Punkte zu beachten sind, dass
1. die Zeichenfolge nie Leerzeichen enthalten. (-, *,/+), und die Zeichen ‚(‘ und ‚)‘

ich für eine Regex in PHP suchen die aufzuspalten
2. die Zeichenfolge wird immer eine Kombination aus Zahlen, arithmetische Symbole sein Zeichen basierend auf ihrem Typ und bilden ein Array von einzelnen Zeichenfolge Zeichen wie unten.
:

a (Anmerkung I str_split nicht verwenden kann, weil ich Zahlen will mehr als 10 nicht aufgeteilt werden.). 1+2+3
output =>[
0 => '1'
1 => '+'
2 => '2'
3 => '+'
4 => '3'
]

b. 2/1*100
output =>[
0 => '2'
1 => '/'
2 => '1'
3 => '*'
4 => '100'
] `

c. 1+2+3/3*100

output =>[
0 => '1'
1 => '+'
2 => '2'
3 => '+'
4 => '3'
5 => '/'
6 => '3'
7 => '*'
8 => '100'
] `

d.(1*2)/(3*4)*100

output =>[
0 => '('
1 => '1'
2 => '*'
3 => '2'
4 => ')'
5 => '/'
6 => '('
7 => '3'
8 => '*'
9 => '4'
10 => ')'
11 => '*'
12 => '100'
]

Vielen Dank im Voraus.

+2

Willkommen bei StackOverflow. Leider ist dies weder eine Tutorialseite noch ein Ersatz für die Websuche. Wir können jedoch helfen, [bestimmte Probleme am Thema] (https://stackoverflow.com/help/on-topic) zu lösen, aber es ist ** dein ** Job, [einige Anstrengungen zu machen] (http: // meta. stackoverflow.com/questions/261592) zu dem Thema an erster Stelle, einschließlich elementarer [(re) search] (https://google.com/). –

+0

Versuchen Sie, es zu tun und den Code bereitzustellen, und ich werde mit Ihnen einen einfacheren Weg teilen, dies zu tun. – ksjohn

+1

Sie sollten einen Parser für solche Arbeit schreiben. – Toto

Antwort

1

verwenden regex:
(?<=[()\/*+-])(?=[0-9()])|(?<=[0-9()])(?=[()\/*+-])

Es wird jede Position zwischen einer Ziffer oder einer Klammer und einem Operator oder einer Klammer übereinstimmen.
(?<=[()\/*+-])(?=[0-9()]) entspricht der Position mit einer Klammer oder einem Operator auf der linken Seite und einer Ziffer oder Klammer auf der rechten Seite
(?<=[0-9()])(?=[()\/*+-]) ist das gleiche, aber mit links und rechts umgekehrt.

Demo here

+0

Danke. Die Regex scheint zu funktionieren, aber wenn ich den folgenden Code benutze - $ re = '/ (? <= [(() \/* + -]) (? = [0-9()]) | (? <= [0-9()]) (? = [() \/* + -])/m '; $ str = '1 + 2 + 3'; preg_match_all ($ re, $ str, $ Übereinstimmungen, PREG_SET_ORDER, 0); Ich bekomme die untere Ausgabe mit leeren Werten. Array: 4 [▼ 0 => array: 1 [▼ 0 => "" ] 1 => array: 1 [▼ 0 => "" ] ] Ich möchte das Array haben, wie (1, +, 2, +, 3). –

+0

Ich liege falsch. Danke, aber ich habe selten Regex verwendet und kann nicht an ihnen arbeiten. –

+0

@ChaitraHegde Ich denke, dass Sie die Funktion preg_split anstelle von preg_match_all verwenden möchten. http://php.net/manual/fr/function.preg-split.php – Gawil

0

Wie gesagt, werde ich dir helfen, wenn Sie selbst eine Arbeit, die Sie haben zur Verfügung stellen können, dieses Problem zu lösen.

Wenn Sie jedoch ein eindimensionales Array aus einem arithmetischen Ausdruck erstellen, besteht Ihr Ziel darin, diesen Array zu analysieren und zu kippen, dann sollten Sie stattdessen einen Baum erstellen und ihn hierarchisieren, indem Sie die Operatoren als Operanden verwenden :

'(1*2)/(3*4)*100' 

Array 
(
    [operand] => '*', 
    [left] => Array 
     (
      [operand] => '/', 
      [left] => Array 
       (
        [operand] => '*', 
        [left] => 1, 
        [right] => 2 
       ), 
      [right] => Array 
       (
        [operand] => '*', 
        [left] => 3, 
        [right] => 4 
       ) 
     ), 
    [right] => 100 
) 
1

Da Sie feststellen, dass die Ausdrücke „sauber“, keine Leer- oder solche sind, könnten Sie auf

\b|(?<=\W)(?=\W) 

Es spaltet auf allen Wortgrenzen und bou gespalten ndaries zwischen Nicht-Wort-Zeichen (mit positiven Lookarounds, die einer Position zwischen zwei Nicht-Wort-Zeichen entsprechen).

See an illustration here at regex101

0

Es gibt keine Notwendigkeit Regex für diese zu verwenden. Sie durchlaufen einfach die Zeichenfolge und erstellen das Array wie gewünscht.

Bearbeiten, nur festgestellt, es kann viel schneller mit einer while-Schleife statt zwei für Schleifen und if() getan werden.

$str ="(10*2)/(3*40)*100"; 
$str = str_split($str); // make str an array 

$arr = array(); 
$j=0; // counter for new array 
for($i=0;$i<count($str);$i++){ 
    if(is_numeric($str[$i])){ // if the item is a number 
     $arr[$j] = $str[$i]; // add it to new array 
     $k = $i+1; 
     while(is_numeric($str[$k])){ // while it's still a number append to new array item. 
      $arr[$j] .= $str[$k]; 
      $k++; // add one to counter. 
      if($k == count($str)) break; // if counter is out of bounds, break loop. 
     } 
     $j++; // we are done with this item, add one to counter. 
     $i=$k-1; // set new value to $i 
    }else{ 
     // not number, add it to the new array and add one to array counter. 
     $arr[$j] = $str[$i]; 
     $j++; 
    } 
} 

var_dump($arr); 

https://3v4l.org/p9jZp

0

Sie können auch diese passende Regex verwenden: [()+\-*\/]|\d+

Demo

0

Ich war für eine PHP-Rechner Demo etwas Ähnliches wie dies zu tun. A related post.

Betrachten Sie dieses Muster für preg_split():

~-?\d+|[()*/+-]~ (Pattern Demo)

Dies hat den zusätzlichen Vorteil, dass negative Zahlen, ohne sie für die Betreiber verwirrend. Die erste "Alternative" passt positive oder negative ganze Zahlen an, während die zweite "Alternative (nach der |) Klammern und Operatoren nacheinander anpasst.

In der PHP-Implementierung lege ich das gesamte Muster in eine Erfassungsgruppe und behalten die Begrenzer auf diese Weise keine Strings zurückgelassen werden ~ als Muster Trennzeichen verwendet, so dass der Schrägstrich in dem Muster nicht entgangen werden muss

Code:... (Demo)

$expression='(1*2)/(3*4)*100+-10'; 
var_export(preg_split('~(-?\d+|[()*/+-])~',$expression,NULL,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE)); 

Ausgabe:

array (
    0 => '(', 
    1 => '1', 
    2 => '*', 
    3 => '2', 
    4 => ')', 
    5 => '/', 
    6 => '(', 
    7 => '3', 
    8 => '*', 
    9 => '4', 
    10 => ')', 
    11 => '*', 
    12 => '100', 
    13 => '+', 
    14 => '-10', 
) 
+0

@ChaitraHegde Wenn Sie die Effizienz in Schritten zwischen der derzeit akzeptierten Antwort und meinem Muster mit Ihren vier Testfallzeichenfolgen vergleichen, wird meine Methode ungefähr 4x schneller. Diese Antwort kann mit meinem anderen Post zusammengeführt werden, um Dezimalstellen zuzulassen, wenn Sie dies wünschen. – mickmackusa

Verwandte Themen