2011-04-25 61 views
0

所以我正在使用Shunting-Yard算法處理來自XML字符串的一些數學運算。訣竅是我想通過使用逗號分隔列表來允許隨機值的生成。例如...在調車場之前處理逗號分隔列表

((3 + 4) * 12) * (2, 3, 4, 5)) 

我已經有一個基本的Shunting-Yard處理器工作。但是我想在處理表達式之前預處理字符串以從列表中隨機選擇一個值。這樣,我可能會結束:

((3 + 4) * 12) * 4) 

分流碼的設置已經是相當複雜的,就我的理解而言,所以我很猶豫,試圖改變它來處理這個問題。處理錯誤檢查聽起來像一場噩夢。因此,我認爲事先尋找這種模式是有意義的?我正在考慮使用一個正則表達式,但我不是「那些」人之一......雖然我希望我是......而當我找到一些examples時,我不確定我會如何修改它們首先檢查括號?我也不相信這將是最好的解決方案。請注意,如果解決方案是正則表達式,它應該能夠在逗號列表中匹配字符串(只是字符,無符號),因爲我將在我的分流中處理特定的字符串值 - 實施。

感謝您的提前想法。

+0

您正在使用什麼語言,解析這個? – ridgerunner 2011-04-25 14:53:40

+0

AS3,所以雖然我很欣賞具體的答案,但我試着讓問題更一般。 – grey 2011-04-26 03:17:55

+1

當提出正則表達式問題時,指定語言很重要,因爲每種語言都有不同的正則表達式能力(正確答案取決於這些能力)。例如,現在我知道您正在使用AS3(使用Javascript正則表達式「flavor」),實際上正確的答案是簡化的。看到我更新的答案。 – ridgerunner 2011-04-26 13:53:37

回答

1

這很容易解決使用兩個正則表達式。適用於整體文本的第一個正則表達式匹配逗號分隔值的每個加括號列表。應用於每個先前匹配列表的第二個正則表達式匹配列表中的每個值。下面是有功能的PHP腳本,考慮具有多個列表的輸入文本,替換其值中的一個隨機選擇的每個列表:

<?php // test.php 20110425_0900 

function substitute_random_value($text) { 
    $re = '/ 
     # Match parenthesized list of comma separated words. 
     \(   # Opening delimiter. 
     \s*   # Optional whitespace. 
     \w+   # required first value. 
     (?:   # Group for additional values. 
      \s* , \s* # Values separated by a comma, ws 
      \w+  # Next value. 
     )+   # One or more additional values. 
     \s*   # Optional whitespace. 
     \)   # Closing delimiter. 
     /x'; 
    // Match each parenthesized list and replace with one of the values. 
    $text = preg_replace_callback($re, '_srv_callback', $text); 
    return $text; 
} 
function _srv_callback($matches_paren) { 
    // Grab all word options in parenthesized list into $matches. 
    $count = preg_match_all('/\w+/', $matches_paren[0], $matches); 
    // Randomly pick one of the matches and return it. 
    return $matches[0][rand(0, $count - 1)]; 
} 

// Read input text 
$data_in = file_get_contents('testdata.txt'); 

// Process text multiple times to verify random replacements. 
$data_out = "Run 1:\n". substitute_random_value($data_in); 
$data_out .= "Run 2:\n". substitute_random_value($data_in); 
$data_out .= "Run 3:\n". substitute_random_value($data_in); 

// Write output text 
file_put_contents('testdata_out.txt', $data_out); 

?> 

substitute_random_value()函數調用PHP preg_replace_callback()功能,它匹配和用列表中的一個值替換每個列表。它調用_srv_callback()函數,隨機選取其中一個值並將其作爲重置值返回。

鑑於這種輸入測試數據(testdata.txt):

((3 + 4) * 12) * (2, 3, 4, 5))
((3 + 4) * 12) * (12, 13))
((3 + 4) * 12) * (22, 23, 24))
((3 + 4) * 12) * (32, 33, 34, 35))

這裏是從腳本的一個例子的運行的輸出:

Run 1:

((3 + 4) * 12) * 13)
((3 + 4) * 12) * 22)
((3 + 4) * 12) * 35)
Run 2:
((3 + 4) * 12) * 3)
((3 + 4) * 12) * 12)
((3 + 4) * 12) * 22)
((3 + 4) * 12) * 33)
Run 3:
((3 + 4) * 12) * 3)
((3 + 4) * 12) * 12)
((3 + 4) * 12) * 23)
((3 + 4) * 12) * 32)

注意,該解決方案使用\w+以匹配由 「字」 的字符,即,[A-ZA-Z0-9_]值。如果這不符合您的要求,可以輕鬆更改。

編輯:這裏是substitute_random_value()功能的JavaScript版本:

function substitute_random_value(text) { 
    // Replace each parenthesized list with one of the values. 
    return text.replace(/\(\s*\w+(?:\s*,\s*\w+)+\s*\)/g, 
     function (m0) { 
      // Capture all word values in parenthesized list into values. 
      var values = m0.match(/\w+/g); 
      // Randomly pick one of the matches and return it. 
      return values[Math.floor(Math.random() * values.length)]; 
     }); 
} 
+0

謝謝。我會試試這個報告。 – grey 2011-04-25 19:45:46

+0

感謝您的澄清。它很好地完成了這項工作。 – grey 2011-04-26 19:01:42

+0

\(\ s * \ - ?\ w +(?:\ s *,\ s * \ - ?\ w +)+ \ s * \)&\ - ?\ w + - 我做了一個修改,添加\ - ? \ w's之前也要匹配負數。在其他人需要的情況下。 – grey 2011-04-27 02:58:06