2017-08-10 106 views
-3

我有一個算術字符串,將類似於以下模式。正則表達式將字符串拆分爲數組和字符使用PHP

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

需要注意的事項是
1.字符串絕不會包含空格。
2.字符串將始終是數字,算術符號(+, - ,*,/)和字符'('和')'的組合

我正在尋找一個PHP正則表達式來分割字符基於它們的類型並形成如下的單個字符串字符的數組。

一個(注意,因爲我想數字比10不被分裂更大的我不能使用str_split)。 1+2+3
輸出=>[
0 => '1'
1 => '+'
2 => '2'
3 => '+'
4 => '3'
]

2/1*100
輸出=>[
0 => '2'
1 => '/'
2 => '1'
3 => '*'
4 => '100'
]`

℃。​​

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

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

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

非常感謝你提前。

+2

歡迎來到StackOverflow。不幸的是,這既不是教程網站,也不是網絡搜索替代品然而,我們可以幫助解決[某些主題上的問題](https://stackoverflow.com/help/on-topic),但它是**你的**工作[付出一些努力](http:// meta。 stackoverflow.com/questions/261592),其中包括初級[(重新)搜索](https://google.com/)。 –

+0

儘量做到這一點,並提供代碼,我會與你分享一個更簡單的方法來做到這一點。 – ksjohn

+1

你最好爲這樣的工作寫一個解析器。 – Toto

回答

1

使用這個表達式:
(?<=[()\/*+-])(?=[0-9()])|(?<=[0-9()])(?=[()\/*+-])

它將數字或括號和運算符或括號之間的每個位置匹配。
(?<=[()\/*+-])(?=[0-9()])與左括號或運算符匹配的位置和右邊的數字或括號
(?<=[0-9()])(?=[()\/*+-])是相同的,但左右顛倒。

演示here

+0

謝謝。正則表達式似乎工作,但是當我運行下面的代碼 - $ re ='/(?<= [()\/* + - ])(?= [0-9()])|(?<= [0-9()])(= [()\/* + - ])/ M'; $ str ='1 + 2 + 3'; preg_match_all($ re,$ str,$ matches,PREG_SET_ORDER,0);我得到下面的輸出與空白值。陣列:4 [▼ 0 =>數組:1 [▼ 0 => 「」 ] 1 =>數組:1 [▼ 0 => 「」 ] ]我想有數組作爲( 1,+,2,+,3)。 –

+0

我運行錯了嗎。謝謝,但我很少使用正則表達式,因此無法開始工作。 –

+0

@ChaitraHegde我想你想使用preg_split函數,而不是preg_match_all。 http://php.net/manual/fr/function.preg-split.php – Gawil

0

正如我所說的,我會幫助你,如果你能提供一些工作,你沒有通過自己來解決這個問題。但是,如果從算術表達式中構造出一維數組,則您的目標是解析併合並該數組,然後您應該構建一棵樹,並通過將操作符作爲節點進行層次化,分支是操作數:

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

既然你聲明的表述是「乾淨」的,沒有空格或這樣,你可能分裂的

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

它分割上的所有單詞邊界 BOU ndaries之間的非單詞字符(使用肯定的lookarounds匹配兩個非單詞字符之間的位置)。

See an illustration here at regex101

0

沒有必要使用正則表達式這一點。您只需循環遍歷字符串並根據需要構建數組。

編輯,只是意識到它可以用一個while循環而不是兩個for循環和if()來快得多。

$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

您也可以使用此匹配的正則表達式:[()+\-*\/]|\d+

Demo

0

我在做類似這樣的PHP計算器演示的東西。 A related post

考慮這個模式來preg_split()

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

這樣具有允許負數不混淆它們爲運營商的好處。第一個「替代」匹配正整數或負整數,而第二個「替代方案」(在|之後)匹配括號和運算符 - 一次一個。

在php實現中,我將整個模式置於捕獲組並保留分隔符這樣子沒有被留下~作爲分隔符的圖案,使該圖案中的斜線不需要進行轉義

代碼:。(Demo

$expression='(1*2)/(3*4)*100+-10'; 
var_export(preg_split('~(-?\d+|[()*/+-])~',$expression,NULL,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE)); 
輸出:
array (
    0 => '(', 
    1 => '1', 
    2 => '*', 
    3 => '2', 
    4 => ')', 
    5 => '/', 
    6 => '(', 
    7 => '3', 
    8 => '*', 
    9 => '4', 
    10 => ')', 
    11 => '*', 
    12 => '100', 
    13 => '+', 
    14 => '-10', 
) 
+0

@ChaitraHegde當使用四個測試用例字符串比較當前接受的答案和我的模式之間的步驟效率時,我的方法將大致快4倍。這個答案可以與我的其他帖子合併,以允許小數點,如果你願意。 – mickmackusa

相關問題